New test.
[mono.git] / mcs / gmcs / anonymous-methods.diff
1 Index: report.cs
2 ===================================================================
3 --- report.cs   (revision 63019)
4 +++ report.cs   (working copy)
5 @@ -634,6 +634,10 @@
6                         : base (message)
7                 {
8                 }
9 +
10 +               public InternalErrorException (string message, params object[] args)
11 +                       : base (String.Format (message, args))
12 +               { }
13         }
14  
15         /// <summary>
16 Index: generic.cs
17 ===================================================================
18 --- generic.cs  (revision 63019)
19 +++ generic.cs  (working copy)
20 @@ -151,11 +151,14 @@
21                 }
22  
23                 public override string TypeParameter {
24 -                       get {
25 -                               return name;
26 -                       }
27 +                       get { return name; }
28                 }
29  
30 +               public Constraints Clone ()
31 +               {
32 +                       return new Constraints (name, constraints, loc);
33 +               }
34 +
35                 GenericParameterAttributes attrs;
36                 TypeExpr class_constraint;
37                 ArrayList iface_constraints;
38 @@ -739,7 +742,7 @@
39                                                 TypeManager.CSharpName (mparam), TypeManager.CSharpSignature (mb));
40                                         return false;
41                                 }
42 -                       } else if (DeclSpace is Iterator) {
43 +                       } else if (DeclSpace is CompilerGeneratedClass) {
44                                 TypeParameter[] tparams = DeclSpace.TypeParameters;
45                                 Type[] types = new Type [tparams.Length];
46                                 for (int i = 0; i < tparams.Length; i++)
47 @@ -2622,7 +2625,7 @@
48  
49                                 Argument a = (Argument) arguments [i];
50                                 if ((a.Expr is NullLiteral) || (a.Expr is MethodGroupExpr) ||
51 -                                   (a.Expr is AnonymousMethod))
52 +                                   (a.Expr is AnonymousMethodExpression))
53                                         continue;
54  
55                                 arg_types [i] = a.Type;
56 Index: typemanager.cs
57 ===================================================================
58 --- typemanager.cs      (revision 63019)
59 +++ typemanager.cs      (working copy)
60 @@ -71,6 +71,7 @@
61         static public Type asynccallback_type;
62         static public Type intptr_type;
63         static public Type monitor_type;
64 +       static public Type interlocked_type;
65         static public Type runtime_field_handle_type;
66         static public Type runtime_argument_handle_type;
67         static public Type attribute_type;
68 @@ -974,6 +975,7 @@
69                 icloneable_type      = CoreLookupType ("System", "ICloneable");
70                 iconvertible_type    = CoreLookupType ("System", "IConvertible");
71                 monitor_type         = CoreLookupType ("System.Threading", "Monitor");
72 +               interlocked_type     = CoreLookupType ("System.Threading", "Interlocked");
73                 intptr_type          = CoreLookupType ("System", "IntPtr");
74  
75                 attribute_type       = CoreLookupType ("System", "Attribute");
76 Index: parameter.cs
77 ===================================================================
78 --- parameter.cs        (revision 63019)
79 +++ parameter.cs        (working copy)
80 @@ -208,10 +208,16 @@
81                 public Expression TypeName;
82                 public readonly Modifier ModFlags;
83                 public string Name;
84 +               public bool IsCaptured;
85                 GenericConstraints constraints;
86                 protected Type parameter_type;
87                 public readonly Location Location;
88  
89 +               Variable var;
90 +               public Variable Variable {
91 +                       get { return var; }
92 +               }
93 +
94                 IResolveContext resolve_context;
95                 
96                 public Parameter (Expression type, string name, Modifier mod, Attributes attrs, Location loc)
97 @@ -335,6 +341,16 @@
98                         return true;
99                 }
100  
101 +               public void ResolveVariable (ToplevelBlock toplevel, int idx)
102 +               {
103 +                       Report.Debug (64, "PARAMETER RESOLVE VARIABLE", ParameterType, Name, Location);
104 +                       if (toplevel.AnonymousMethodHost != null)
105 +                               var = toplevel.AnonymousMethodHost.GetCapturedParameter (this);
106 +                       Report.Debug (64, "PARAMETER RESOLVE VARIABLE #1", var, idx);
107 +                       if (var == null)
108 +                               var = new ParameterVariable (this, idx);
109 +               }
110 +
111                 public Type ExternalType ()
112                 {
113                         if ((ModFlags & Parameter.Modifier.ISBYREF) != 0)
114 @@ -452,6 +468,78 @@
115                                 return attribute_targets;
116                         }
117                 }
118 +
119 +               protected class ParameterVariable : Variable
120 +               {
121 +                       public readonly Parameter Parameter;
122 +                       public readonly int Idx;
123 +                       public readonly bool IsRef;
124 +
125 +                       public ParameterVariable (Parameter par, int idx)
126 +                       {
127 +                               this.Parameter = par;
128 +                               this.Idx = idx;
129 +                               this.IsRef = (par.ModFlags & Parameter.Modifier.ISBYREF) != 0;
130 +                       }
131 +
132 +                       public override Type Type {
133 +                               get { return Parameter.ParameterType; }
134 +                       }
135 +
136 +                       public override bool HasInstance {
137 +                               get { return false; }
138 +                       }
139 +
140 +                       public override bool NeedsTemporary {
141 +                               get { return false; }
142 +                       }
143 +
144 +                       public override void EmitInstance (EmitContext ec)
145 +                       {
146 +                       }
147 +
148 +                       public override void Emit (EmitContext ec)
149 +                       {
150 +                               int arg_idx = Idx;
151 +                               if (!ec.MethodIsStatic)
152 +                                       arg_idx++;
153 +
154 +                               ParameterReference.EmitLdArg (ec.ig, arg_idx);
155 +                       }
156 +
157 +                       public override void EmitAssign (EmitContext ec)
158 +                       {
159 +                               int arg_idx = Idx;
160 +                               if (!ec.MethodIsStatic)
161 +                                       arg_idx++;
162 +
163 +                               if (arg_idx <= 255)
164 +                                       ec.ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
165 +                               else
166 +                                       ec.ig.Emit (OpCodes.Starg, arg_idx);
167 +                       }
168 +
169 +                       public override void EmitAddressOf (EmitContext ec)
170 +                       {
171 +                               int arg_idx = Idx;
172 +
173 +                               if (!ec.MethodIsStatic)
174 +                                       arg_idx++;
175 +
176 +                               if (IsRef) {
177 +                                       if (arg_idx <= 255)
178 +                                               ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
179 +                                       else
180 +                                               ec.ig.Emit (OpCodes.Ldarg, arg_idx);
181 +                               } else {
182 +                                       if (arg_idx <= 255)
183 +                                               ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
184 +                                       else
185 +                                               ec.ig.Emit (OpCodes.Ldarga, arg_idx);
186 +                               }
187 +                       }
188 +               }
189 +
190         }
191  
192         /// <summary>
193 @@ -607,6 +695,14 @@
194                         return ok;
195                 }
196  
197 +               public void ResolveVariable (ToplevelBlock toplevel)
198 +               {
199 +                       for (int i = 0; i < FixedParameters.Length; ++i) {
200 +                               Parameter p = FixedParameters [i];
201 +                               p.ResolveVariable (toplevel, i);
202 +                       }
203 +               }
204 +
205                 public CallingConventions CallingConvention
206                 {
207                         get {
208 @@ -665,7 +761,7 @@
209                         }
210                 }
211  
212 -               Parameter this [int pos]
213 +               public Parameter this [int pos]
214                 {
215                         get {
216                                 if (pos >= count && (HasArglist || HasParams)) {
217 Index: modifiers.cs
218 ===================================================================
219 --- modifiers.cs        (revision 63019)
220 +++ modifiers.cs        (working copy)
221 @@ -36,6 +36,7 @@
222                 //
223                 public const int METHOD_YIELDS = 0x8000;
224                 public const int METHOD_GENERIC = 0x10000;
225 +               public const int ANONYMOUS_HOST = 0x20000;
226  
227                 public const int Accessibility =
228                         PUBLIC | PROTECTED | INTERNAL | PRIVATE;
229 Index: rootcontext.cs
230 ===================================================================
231 --- rootcontext.cs      (revision 63019)
232 +++ rootcontext.cs      (working copy)
233 @@ -377,6 +377,7 @@
234                                 "System.Runtime.CompilerServices.RuntimeHelpers",
235                                 "System.Reflection.DefaultMemberAttribute",
236                                 "System.Threading.Monitor",
237 +                               "System.Threading.Interlocked",
238                                 
239                                 "System.AttributeUsageAttribute",
240                                 "System.Runtime.InteropServices.DllImportAttribute",
241 Index: ecore.cs
242 ===================================================================
243 --- ecore.cs    (revision 63019)
244 +++ ecore.cs    (working copy)
245 @@ -3146,8 +3146,6 @@
246                                                         "this");
247                                                 return null;
248                                         }
249 -                                       if ((am.ContainerAnonymousMethod == null) && (InstanceExpression is This))
250 -                                               ec.CaptureField (this);
251                                 }
252                         }
253                         
254 @@ -4007,10 +4005,10 @@
255                 }
256         }
257  
258 -       
259         public class TemporaryVariable : Expression, IMemoryLocation
260         {
261                 LocalInfo li;
262 +               Variable var;
263                 
264                 public TemporaryVariable (Type type, Location loc)
265                 {
266 @@ -4028,64 +4026,47 @@
267                         li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
268                         if (!li.Resolve (ec))
269                                 return null;
270 +
271 +                       if (ec.MustCaptureVariable (li)) {
272 +                               ScopeInfo scope = li.Block.CreateScopeInfo ();
273 +                               var = scope.AddLocal (li);
274 +                               type = var.Type;
275 +                       }
276                         
277 -                       AnonymousContainer am = ec.CurrentAnonymousMethod;
278 -                       if ((am != null) && am.IsIterator)
279 -                               ec.CaptureVariable (li);
280 -                       
281                         return this;
282                 }
283 +
284 +               public Variable Variable {
285 +                       get { return var != null ? var : li.Variable; }
286 +               }
287                 
288                 public override void Emit (EmitContext ec)
289                 {
290 -                       ILGenerator ig = ec.ig;
291 -                       
292 -                       if (li.FieldBuilder != null) {
293 -                               ig.Emit (OpCodes.Ldarg_0);
294 -                               ig.Emit (OpCodes.Ldfld, li.FieldBuilder);
295 -                       } else {
296 -                               ig.Emit (OpCodes.Ldloc, li.LocalBuilder);
297 -                       }
298 +                       Variable.EmitInstance (ec);
299 +                       Variable.Emit (ec);
300                 }
301                 
302                 public void EmitLoadAddress (EmitContext ec)
303                 {
304 -                       ILGenerator ig = ec.ig;
305 -                       
306 -                       if (li.FieldBuilder != null) {
307 -                               ig.Emit (OpCodes.Ldarg_0);
308 -                               ig.Emit (OpCodes.Ldflda, li.FieldBuilder);
309 -                       } else {
310 -                               ig.Emit (OpCodes.Ldloca, li.LocalBuilder);
311 -                       }
312 +                       Variable.EmitInstance (ec);
313 +                       Variable.EmitAddressOf (ec);
314                 }
315                 
316                 public void Store (EmitContext ec, Expression right_side)
317                 {
318 -                       if (li.FieldBuilder != null)
319 -                               ec.ig.Emit (OpCodes.Ldarg_0);
320 -                       
321 +                       Variable.EmitInstance (ec);
322                         right_side.Emit (ec);
323 -                       if (li.FieldBuilder != null) {
324 -                               ec.ig.Emit (OpCodes.Stfld, li.FieldBuilder);
325 -                       } else {
326 -                               ec.ig.Emit (OpCodes.Stloc, li.LocalBuilder);
327 -                       }
328 +                       Variable.EmitAssign (ec);
329                 }
330                 
331                 public void EmitThis (EmitContext ec)
332                 {
333 -                       if (li.FieldBuilder != null) {
334 -                               ec.ig.Emit (OpCodes.Ldarg_0);
335 -                       }
336 +                       Variable.EmitInstance (ec);
337                 }
338                 
339 -               public void EmitStore (ILGenerator ig)
340 +               public void EmitStore (EmitContext ec)
341                 {
342 -                       if (li.FieldBuilder != null)
343 -                               ig.Emit (OpCodes.Stfld, li.FieldBuilder);
344 -                       else
345 -                               ig.Emit (OpCodes.Stloc, li.LocalBuilder);
346 +                       Variable.EmitAssign (ec);
347                 }
348                 
349                 public void AddressOf (EmitContext ec, AddressOp mode)
350 @@ -4093,5 +4074,5 @@
351                         EmitLoadAddress (ec);
352                 }
353         }
354 -       
355 +
356  }      
357 Index: class.cs
358 ===================================================================
359 --- class.cs    (revision 63019)
360 +++ class.cs    (working copy)
361 @@ -69,8 +69,7 @@
362                                 foreach (MemberCore mc in this) {
363                                         try {
364                                                 mc.Define ();
365 -                                       }
366 -                                       catch (Exception e) {
367 +                                       } catch (Exception e) {
368                                                 throw new InternalErrorException (mc.Location, mc.GetSignatureForError (), e);
369                                         }
370                                 }
371 @@ -133,7 +132,6 @@
372                                         Report.Warning (659, 3, container.Location, "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", container.GetSignatureForError ());
373                                 }
374                         }
375
376                 }
377  
378                 public sealed class IndexerArrayList : MemberCoreArrayList
379 @@ -429,8 +427,8 @@
380                 // Holds the operators
381                 MemberCoreArrayList operators;
382  
383 -               // Holds the iterators
384 -               ArrayList iterators;
385 +               // Holds the compiler generated classes
386 +               ArrayList compiler_generated;
387  
388                 //
389                 // Pointers to the default constructor and the default static constructor
390 @@ -455,6 +453,8 @@
391  
392                 ArrayList type_bases;
393  
394 +               bool type_populated;
395 +               bool type_populated_ok;
396                 bool members_defined;
397                 bool members_defined_ok;
398  
399 @@ -772,12 +772,14 @@
400                         operators.Add (op);
401                 }
402  
403 -               public void AddIterator (Iterator i)
404 +               public void AddCompilerGeneratedClass (CompilerGeneratedClass c)
405                 {
406 -                       if (iterators == null)
407 -                               iterators = new ArrayList ();
408 +                       Report.Debug (64, "ADD COMPILER GENERATED CLASS", this, c);
409  
410 -                       iterators.Add (i);
411 +                       if (compiler_generated == null)
412 +                               compiler_generated = new ArrayList ();
413 +
414 +                       compiler_generated.Add (c);
415                 }
416  
417                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
418 @@ -822,9 +824,9 @@
419                         }
420                 }
421  
422 -               public ArrayList Iterators {
423 +               public ArrayList CompilerGenerated {
424                         get {
425 -                               return iterators;
426 +                               return compiler_generated;
427                         }
428                 }
429  
430 @@ -1202,7 +1204,7 @@
431                         // Let's do it as soon as possible, since code below can call DefineType() on classes
432                         // that depend on us to be populated before they are.
433                         //
434 -                       if (!(this is Iterator))
435 +                       if (!(this is Iterator) && !(this is CompilerGeneratedClass))
436                                 RootContext.RegisterOrder (this); 
437  
438                         if (base_type != null) {
439 @@ -1278,11 +1280,53 @@
440                                         part.TypeBuilder = TypeBuilder;
441                         }
442  
443 +                       if (!CreateAnonymousHelpers ()) {
444 +                               error = true;
445 +                               return null;
446 +                       }
447 +
448                         DefineNestedTypes ();
449  
450                         return TypeBuilder;
451                 }
452  
453 +               protected bool CreateAnonymousHelpers ()
454 +               {
455 +                       if (methods != null) {
456 +                               foreach (Method method in methods) {
457 +                                       if (!method.CreateAnonymousHelpers ())
458 +                                               return false;
459 +                               }
460 +                       }
461 +
462 +                       if (operators != null) {
463 +                               foreach (Operator o in operators) {
464 +                                       if (!o.CreateAnonymousHelpers ())
465 +                                               return false;
466 +                               }
467 +                       }
468 +
469 +                       if (properties != null) {
470 +                               foreach (PropertyBase p in properties) {
471 +                                       if (!p.Get.IsDummy && !p.Get.CreateAnonymousHelpers ())
472 +                                               return false;
473 +                                       if (!p.Set.IsDummy && !p.Set.CreateAnonymousHelpers ())
474 +                                               return false;
475 +                               }
476 +                       }
477 +
478 +                       if (indexers != null) {
479 +                               foreach (PropertyBase p in indexers) {
480 +                                       if (!p.Get.IsDummy && !p.Get.CreateAnonymousHelpers ())
481 +                                               return false;
482 +                                       if (!p.Set.IsDummy && !p.Set.CreateAnonymousHelpers ())
483 +                                               return false;
484 +                               }
485 +                       }
486 +
487 +                       return true;
488 +               }
489 +
490                 Constraints [] constraints;
491                 public override void SetParameterInfo (ArrayList constraints_list)
492                 {
493 @@ -1329,6 +1373,20 @@
494  
495                 public bool ResolveType ()
496                 {
497 +                       if (!DoResolveType ())
498 +                               return false;
499 +
500 +                       if (compiler_generated != null) {
501 +                               foreach (CompilerGeneratedClass c in compiler_generated)
502 +                                       if (!c.ResolveType ())
503 +                                               return false;
504 +                       }
505 +
506 +                       return true;
507 +               }
508 +
509 +               protected virtual bool DoResolveType ()
510 +               {
511                         if ((base_type != null) &&
512                             (base_type.ResolveAsTypeTerminal (this, false) == null)) {
513                                 error = true;
514 @@ -1413,6 +1471,13 @@
515                                                 return false;
516                         }
517  
518 +                       if (compiler_generated != null) {
519 +                               foreach (CompilerGeneratedClass c in compiler_generated) {
520 +                                       if (c.DefineType () == null)
521 +                                               return false;
522 +                               }
523 +                       }
524 +
525                         return true;
526                 }
527  
528 @@ -1462,6 +1527,22 @@
529                         Report.Error (1530, loc, "Keyword `new' is not allowed on namespace elements");
530                 }
531  
532 +               protected bool PopulateType ()
533 +               {
534 +                       if (type_populated)
535 +                               return type_populated_ok;
536 +
537 +                       type_populated_ok = DoPopulateType ();
538 +                       type_populated = true;
539 +
540 +                       return type_populated_ok;
541 +               }
542 +
543 +               protected virtual bool DoPopulateType ()
544 +               {
545 +                       return true;
546 +               }
547 +
548                 /// <summary>
549                 ///   Populates our TypeBuilder with fields and methods
550                 /// </summary>
551 @@ -1541,18 +1622,7 @@
552                                         part.member_cache = member_cache;
553                         }
554  #endif
555 -                       if (iterators != null) {
556 -                               foreach (Iterator iterator in iterators) {
557 -                                       if (iterator.DefineType () == null)
558 -                                               return false;
559 -                               }
560  
561 -                               foreach (Iterator iterator in iterators) {
562 -                                       if (!iterator.DefineMembers ())
563 -                                               return false;
564 -                               }
565 -                       }
566 -
567                         return true;
568                 }
569  
570 @@ -1564,9 +1634,9 @@
571  
572                 public override bool Define ()
573                 {
574 -                       if (iterators != null) {
575 -                               foreach (Iterator iterator in iterators) {
576 -                                       if (!iterator.Define ())
577 +                       if (compiler_generated != null) {
578 +                               foreach (CompilerGeneratedClass c in compiler_generated) {
579 +                                       if (!c.Define ())
580                                                 return false;
581                                 }
582                         }
583 @@ -2239,7 +2309,7 @@
584  
585                         if (default_static_constructor != null)
586                                 default_static_constructor.Emit ();
587 -                       
588 +
589                         if (methods != null){
590                                 foreach (Method m in methods)
591                                         m.Emit ();
592 @@ -2282,9 +2352,14 @@
593                                 if (pending.VerifyPendingMethods ())
594                                         return;
595  
596 -                       if (iterators != null)
597 -                               foreach (Iterator iterator in iterators)
598 -                                       iterator.EmitType ();
599 +                       if (compiler_generated != null) {
600 +                               foreach (CompilerGeneratedClass c in compiler_generated) {
601 +                                       if (!c.DefineMembers ())
602 +                                               throw new InternalErrorException ();
603 +                               }
604 +                               foreach (CompilerGeneratedClass c in compiler_generated)
605 +                                       c.EmitType ();
606 +                       }
607                 }
608                 
609                 public override void CloseType ()
610 @@ -2324,9 +2399,9 @@
611                                 foreach (Delegate d in Delegates)
612                                         d.CloseType ();
613  
614 -                       if (Iterators != null)
615 -                               foreach (Iterator i in Iterators)
616 -                                       i.CloseType ();
617 +                       if (CompilerGenerated != null)
618 +                               foreach (CompilerGeneratedClass c in CompilerGenerated)
619 +                                       c.CloseType ();
620                         
621                         types = null;
622                         properties = null;
623 @@ -2341,7 +2416,7 @@
624                         events = null;
625                         indexers = null;
626                         operators = null;
627 -                       iterators = null;
628 +                       compiler_generated = null;
629                         default_constructor = null;
630                         default_static_constructor = null;
631                         type_bases = null;
632 @@ -3194,7 +3269,7 @@
633                         }
634                 }
635  
636 -               public void SetYields ()
637 +               public virtual void SetYields ()
638                 {
639                         ModFlags |= Modifiers.METHOD_YIELDS;
640                 }
641 @@ -3652,6 +3727,9 @@
642                 ListDictionary declarative_security;
643                 protected MethodData MethodData;
644  
645 +               Iterator iterator;
646 +               ArrayList anonymous_methods;
647 +
648                 static string[] attribute_targets = new string [] { "method", "return" };
649  
650                 protected MethodOrOperator (DeclSpace parent, GenericMethod generic, Expression type, int mod,
651 @@ -3702,24 +3780,29 @@
652                         }
653                 }
654  
655 -               public EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
656 +               public virtual EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
657                 {
658 -                       EmitContext ec = new EmitContext (this,
659 -                               tc, this.ds, Location, ig, MemberType, ModFlags, false);
660 +                       return new EmitContext (
661 +                               this, tc, this.ds, Location, ig, MemberType, ModFlags, false);
662 +               }
663  
664 -                       Iterator iterator = tc as Iterator;
665 -                       if (iterator != null)
666 -                               ec.CurrentAnonymousMethod = iterator.Host;
667 -
668 -                       return ec;
669 +               public void AddAnonymousMethod (AnonymousMethodExpression anonymous)
670 +               {
671 +                       if (anonymous_methods == null)
672 +                               anonymous_methods = new ArrayList ();
673 +                       anonymous_methods.Add (anonymous);
674                 }
675  
676 -               public override bool Define ()
677 +               bool base_defined;
678 +
679 +               protected bool DefineGenericMethod ()
680                 {
681 +                       if (base_defined)
682 +                               return true;
683 +
684                         if (!DoDefineBase ())
685                                 return false;
686  
687 -                       MethodBuilder mb = null;
688                         if (GenericMethod != null) {
689                                 string method_name = MemberName.Name;
690  
691 @@ -3728,12 +3811,49 @@
692                                                 '.' + method_name;
693                                 }
694  
695 -                               mb = Parent.TypeBuilder.DefineMethod (method_name, flags);
696 +                               MethodBuilder = Parent.TypeBuilder.DefineMethod (method_name, flags);
697  
698 -                               if (!GenericMethod.Define (mb))
699 +                               if (!GenericMethod.Define (MethodBuilder))
700                                         return false;
701                         }
702  
703 +                       base_defined = true;
704 +                       return true;
705 +               }
706 +
707 +               public bool CreateAnonymousHelpers ()
708 +               {
709 +                       Report.Debug (64, "METHOD DEFINE HELPERS", this, Name,
710 +                                     ModFlags & Modifiers.METHOD_YIELDS,
711 +                                     ModFlags & Modifiers.ANONYMOUS_HOST,
712 +                                     Block);
713 +
714 +                       if (!DefineGenericMethod ())
715 +                               return false;
716 +
717 +                       if ((ModFlags & Modifiers.METHOD_YIELDS) != 0) {
718 +                               iterator = Iterator.CreateIterator (
719 +                                       this, ParentContainer, GenericMethod, ModFlags);
720 +
721 +                               if (iterator == null)
722 +                                       return false;
723 +                       }
724 +
725 +                       if (anonymous_methods != null) {
726 +                               foreach (AnonymousMethodExpression ame in anonymous_methods) {
727 +                                       if (!ame.CreateAnonymousHelpers ())
728 +                                               return false;
729 +                               }
730 +                       }
731 +
732 +                       return true;
733 +               }
734 +
735 +               public override bool Define ()
736 +               {
737 +                       if (!DefineGenericMethod ())
738 +                               return false;
739 +
740                         if (!DoDefine ())
741                                 return false;
742  
743 @@ -3743,7 +3863,8 @@
744                         if (!CheckBase ())
745                                 return false;
746  
747 -                       MethodData = new MethodData (this, ModFlags, flags, this, mb, GenericMethod, base_method);
748 +                       MethodData = new MethodData (
749 +                               this, ModFlags, flags, this, MethodBuilder, GenericMethod, base_method);
750  
751                         if (!MethodData.Define (ParentContainer))
752                                 return false;
753 @@ -3821,6 +3942,10 @@
754                         }
755                 }
756  
757 +               public Iterator Iterator {
758 +                       get { return iterator; }
759 +               }
760 +
761                 public new Location Location {
762                         get {
763                                 return base.Location;
764 @@ -3961,7 +4086,7 @@
765                 }
766         }
767  
768 -       public class Method : MethodOrOperator, IIteratorContainer {
769 +       public class Method : MethodOrOperator, IAnonymousHost {
770  
771                 /// <summary>
772                 ///   Modifiers allowed in a class declaration
773 @@ -3978,7 +4103,8 @@
774                         Modifiers.OVERRIDE |
775                         Modifiers.ABSTRACT |
776                         Modifiers.UNSAFE |
777 -                       Modifiers.METHOD_YIELDS | 
778 +                       Modifiers.METHOD_YIELDS |
779 +                       Modifiers.ANONYMOUS_HOST |
780                         Modifiers.EXTERN;
781  
782                 const int AllowedInterfaceModifiers =
783 @@ -4118,6 +4244,8 @@
784                 //
785                 public override bool Define ()
786                 {
787 +                       Report.Debug (64, "METHOD DEFINE", this, Name);
788 +
789                         if (!base.Define ())
790                                 return false;
791  
792 @@ -4132,17 +4260,6 @@
793                         }
794  
795                         //
796 -                       // Setup iterator if we are one
797 -                       //
798 -                       if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
799 -                               Iterator iterator = new Iterator (
800 -                                       this, Parent, GenericMethod, ModFlags);
801 -
802 -                               if (!iterator.DefineIterator ())
803 -                                       return false;
804 -                       }
805 -
806 -                       //
807                         // This is used to track the Entry Point,
808                         //
809                         if (Name == "Main" &&
810 @@ -4179,6 +4296,7 @@
811                 // 
812                 public override void Emit ()
813                 {
814 +                       Report.Debug (64, "METHOD EMIT", this, MethodBuilder, Location, Block, MethodData);
815                         MethodData.Emit (Parent);
816                         base.Emit ();
817  
818 @@ -4360,6 +4478,10 @@
819  
820                 static string[] attribute_targets = new string [] { "method" };
821  
822 +               public Iterator Iterator {
823 +                       get { return null; }
824 +               }
825 +
826                 bool has_compliant_args = false;
827                 //
828                 // The spec claims that static is not permitted, but
829 @@ -4581,6 +4703,13 @@
830                                                 ParentContainer.EmitFieldInitializers (ec);
831                                 }
832                         }
833 +
834 +                       bool unreachable = false;
835 +                       if (block != null) {
836 +                               ec.ResolveTopBlock (null, block, ParameterInfo, this, out unreachable);
837 +                               ec.EmitMeta (block);
838 +                       }
839 +
840                         if (Initializer != null) {
841                                 Initializer.Emit (ec);
842                         }
843 @@ -4588,7 +4717,8 @@
844                         if ((ModFlags & Modifiers.STATIC) != 0)
845                                 ParentContainer.EmitFieldInitializers (ec);
846  
847 -                       ec.EmitTopBlock (this, block);
848 +                       if (block != null)
849 +                               ec.EmitResolvedTopBlock (block, unreachable);
850  
851                         if (source != null)
852                                 source.CloseMethod ();
853 @@ -4710,6 +4840,8 @@
854                 GenericMethod GenericMethod { get; }
855                 Parameters ParameterInfo { get; }
856  
857 +               Iterator Iterator { get; }
858 +
859                 Attributes OptAttributes { get; }
860                 ToplevelBlock Block { get; set; }
861  
862 @@ -5032,6 +5164,20 @@
863                         
864                         SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block);
865  
866 +                       Report.Debug (64, "METHOD DATA EMIT", this, MethodBuilder,
867 +                                     method, method.Iterator, block);
868 +
869 +#if FIXME
870 +                       if (method.Iterator != null) {
871 +                               if (!method.Iterator.Resolve (ec))
872 +                                       throw new InternalErrorException ();
873 +                               // method.Iterator.EmitMethod (ec);
874 +                       }
875 +#endif
876 +
877 +                       Report.Debug (64, "METHOD DATA EMIT #1", this, MethodBuilder,
878 +                                     method, method.Iterator, block);
879 +
880                         //
881                         // Handle destructors specially
882                         //
883 @@ -5860,7 +6006,7 @@
884         //
885         // `set' and `get' accessors are represented with an Accessor.
886         // 
887 -       public class Accessor : IIteratorContainer {
888 +       public class Accessor : IAnonymousHost {
889                 //
890                 // Null if the accessor is empty, or a Block if not
891                 //
892 @@ -5875,6 +6021,7 @@
893                 public Location Location;
894                 public int ModFlags;
895                 public bool Yields;
896 +               public ArrayList AnonymousMethods;
897                 
898                 public Accessor (ToplevelBlock b, int mod, Attributes attrs, Location loc)
899                 {
900 @@ -5888,6 +6035,13 @@
901                 {
902                         Yields = true;
903                 }
904 +
905 +               public void AddAnonymousMethod (AnonymousMethodExpression ame)
906 +               {
907 +                       if (AnonymousMethods == null)
908 +                               AnonymousMethods = new ArrayList ();
909 +                       AnonymousMethods.Add (ame);
910 +               }
911         }
912  
913         // Ooouh Martin, templates are missing here.
914 @@ -5934,6 +6088,10 @@
915  
916                 #region IMethodData Members
917  
918 +               public abstract Iterator Iterator {
919 +                       get;
920 +               }
921 +
922                 public ToplevelBlock Block {
923                         get {
924                                 return block;
925 @@ -6220,6 +6378,8 @@
926                 {
927                         protected readonly MethodCore method;
928                         protected MethodAttributes flags;
929 +                       Iterator iterator;
930 +                       ArrayList anonymous_methods;
931                         bool yields;
932  
933                         public PropertyMethod (MethodCore method, string prefix)
934 @@ -6235,12 +6395,17 @@
935                                 this.method = method;
936                                 this.ModFlags = accessor.ModFlags;
937                                 yields = accessor.Yields;
938 +                               anonymous_methods = accessor.AnonymousMethods;
939  
940                                 if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
941                                         Report.FeatureIsNotStandardized (Location, "access modifiers on properties");
942                                 }
943                         }
944  
945 +                       public override Iterator Iterator {
946 +                               get { return iterator; }
947 +                       }
948 +
949                         public override AttributeTargets AttributeTargets {
950                                 get {
951                                         return AttributeTargets.Method;
952 @@ -6252,6 +6417,28 @@
953                                 return method.IsClsComplianceRequired ();
954                         }
955  
956 +                       public bool CreateAnonymousHelpers ()
957 +                       {
958 +                               TypeContainer container = ((TypeContainer) Parent).PartialContainer;
959 +
960 +                               if (yields) {
961 +                                       iterator = Iterator.CreateIterator (
962 +                                               this, container, null, ModFlags);
963 +
964 +                                       if (iterator == null)
965 +                                               return false;
966 +                               }
967 +
968 +                               if (anonymous_methods != null) {
969 +                                       foreach (AnonymousMethodExpression ame in anonymous_methods) {
970 +                                               if (!ame.CreateAnonymousHelpers ())
971 +                                                       return false;
972 +                                       }
973 +                               }
974 +
975 +                               return true;
976 +                       }
977 +
978                         public virtual MethodBuilder Define (DeclSpace parent)
979                         {
980                                 if (!method.CheckAbstractAndExtern (block != null))
981 @@ -6281,16 +6468,6 @@
982                                         flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
983                                 }
984  
985 -                               //
986 -                               // Setup iterator if we are one
987 -                               //
988 -                               if (yields) {
989 -                                       Iterator iterator = new Iterator (this, Parent as TypeContainer, null, ModFlags);
990 -                                       
991 -                                       if (!iterator.DefineIterator ())
992 -                                               return null;
993 -                               }
994 -
995                                 return null;
996                         }
997  
998 @@ -6932,6 +7109,10 @@
999                                 this.method = method;
1000                         }
1001  
1002 +                       public override Iterator Iterator {
1003 +                               get { return null; }
1004 +                       }
1005 +
1006                         protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
1007                         {
1008                                 if (a.Target == AttributeTargets.Parameter) {
1009 @@ -7183,7 +7364,7 @@
1010         }
1011  
1012   
1013 -       public class Indexer : PropertyBase, IIteratorContainer {
1014 +       public class Indexer : PropertyBase {
1015  
1016                 class GetIndexerMethod : GetMethod
1017                 {
1018 @@ -7323,10 +7504,10 @@
1019                                 // Setup iterator if we are one
1020                                 //
1021                                 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
1022 -                                       Iterator iterator = new Iterator (
1023 -                                               Get, Parent, null, ModFlags);
1024 +                                       Iterator iterator = Iterator.CreateIterator (
1025 +                                               Get, (TypeContainer) Parent, null, ModFlags);
1026  
1027 -                                       if (!iterator.DefineIterator ())
1028 +                                       if (iterator == null)
1029                                                 return false;
1030                                 }
1031                         }
1032 @@ -7383,7 +7564,7 @@
1033                 }
1034         }
1035  
1036 -       public class Operator : MethodOrOperator, IIteratorContainer {
1037 +       public class Operator : MethodOrOperator, IAnonymousHost {
1038  
1039                 const int AllowedModifiers =
1040                         Modifiers.PUBLIC |
1041 Index: decl.cs
1042 ===================================================================
1043 --- decl.cs     (revision 63019)
1044 +++ decl.cs     (working copy)
1045 @@ -525,6 +525,7 @@
1046                                 caching_flags |= Flags.ClsCompliantAttributeTrue;
1047                                 return true;
1048                         }
1049 +
1050                         return false;
1051                 }
1052  
1053 Index: delegate.cs
1054 ===================================================================
1055 --- delegate.cs (revision 63019)
1056 +++ delegate.cs (working copy)
1057 @@ -816,8 +816,8 @@
1058                         
1059                         Expression e = a.Expr;
1060  
1061 -                       if (e is AnonymousMethod && RootContext.Version != LanguageVersion.ISO_1)
1062 -                               return ((AnonymousMethod) e).Compatible (ec, type);
1063 +                       if (e is AnonymousMethodExpression && RootContext.Version != LanguageVersion.ISO_1)
1064 +                               return ((AnonymousMethodExpression) e).Compatible (ec, type);
1065  
1066                         MethodGroupExpr mg = e as MethodGroupExpr;
1067                         if (mg != null)
1068 Index: iterators.cs
1069 ===================================================================
1070 --- iterators.cs        (revision 63019)
1071 +++ iterators.cs        (working copy)
1072 @@ -21,14 +21,6 @@
1073  
1074  namespace Mono.CSharp {
1075  
1076 -       public interface IIteratorContainer {
1077 -
1078 -               //
1079 -               // Invoked if a yield statement is found in the body
1080 -               //
1081 -               void SetYields ();
1082 -       }
1083 -       
1084         public class Yield : Statement {
1085                 Expression expr;
1086                 ArrayList finally_blocks;
1087 @@ -71,16 +63,19 @@
1088                 
1089                 public override bool Resolve (EmitContext ec)
1090                 {
1091 +                       Report.Debug (64, "RESOLVE YIELD", this, ec, expr, expr.GetType ());
1092                         expr = expr.Resolve (ec);
1093                         if (expr == null)
1094                                 return false;
1095  
1096 +                       Report.Debug (64, "RESOLVE YIELD #1", this, ec, expr, expr.GetType (),
1097 +                                     ec.CurrentAnonymousMethod, ec.CurrentIterator);
1098 +
1099                         if (!CheckContext (ec, loc, false))
1100                                 return false;
1101  
1102                         Iterator iterator = ec.CurrentIterator;
1103 -
1104 -                       if (expr.Type != iterator.IteratorType){
1105 +                       if (expr.Type != iterator.IteratorType) {
1106                                 expr = Convert.ImplicitConversionRequired (
1107                                         ec, expr, iterator.IteratorType, loc);
1108                                 if (expr == null)
1109 @@ -119,13 +114,465 @@
1110                 }
1111         }
1112  
1113 -       public class Iterator : Class {
1114 -               protected ToplevelBlock original_block;
1115 -               protected ToplevelBlock block;
1116 +       public class IteratorHost : AnonymousMethodHost
1117 +       {
1118 +               public readonly Iterator Iterator;
1119  
1120 -               Type original_iterator_type;
1121                 TypeExpr iterator_type_expr;
1122 -               bool is_enumerable;
1123 +               Field pc_field;
1124 +               Field current_field;
1125 +               Method dispose;
1126 +               MethodInfo dispose_method;
1127 +
1128 +               TypeExpr enumerator_type;
1129 +               TypeExpr enumerable_type;
1130 +               TypeExpr generic_enumerator_type;
1131 +               TypeExpr generic_enumerable_type;
1132 +               TypeArguments generic_args;
1133 +
1134 +               public IteratorHost (Iterator iterator)
1135 +                       : base (iterator.Container, iterator.Host, iterator.GenericMethod,
1136 +                               iterator.Location)
1137 +               {
1138 +                       this.Iterator = iterator;
1139 +               }
1140 +
1141 +               public MethodInfo Dispose {
1142 +                       get { return dispose_method; }
1143 +               }
1144 +
1145 +               public Field PC {
1146 +                       get { return pc_field; }
1147 +               }
1148 +
1149 +               public Field CurrentField {
1150 +                       get { return current_field; }
1151 +               }
1152 +
1153 +               public Type IteratorType {
1154 +                       get { return iterator_type_expr.Type; }
1155 +               }
1156 +
1157 +               public override TypeExpr [] GetClassBases (out TypeExpr base_class)
1158 +               {
1159 +                       iterator_type_expr = InflateType (Iterator.OriginalIteratorType);
1160 +
1161 +                       generic_args = new TypeArguments (Location);
1162 +                       generic_args.Add (iterator_type_expr);
1163 +
1164 +                       ArrayList list = new ArrayList ();
1165 +                       if (Iterator.IsEnumerable) {
1166 +                               enumerable_type = new TypeExpression (
1167 +                                       TypeManager.ienumerable_type, Location);
1168 +                               list.Add (enumerable_type);
1169 +
1170 +                               generic_enumerable_type = new ConstructedType (
1171 +                                       TypeManager.generic_ienumerable_type,
1172 +                                       generic_args, Location);
1173 +                               list.Add (generic_enumerable_type);
1174 +                       }
1175 +
1176 +                       enumerator_type = new TypeExpression (
1177 +                               TypeManager.ienumerator_type, Location);
1178 +                       list.Add (enumerator_type);
1179 +
1180 +                       list.Add (new TypeExpression (TypeManager.idisposable_type, Location));
1181 +
1182 +                       generic_enumerator_type = new ConstructedType (
1183 +                               TypeManager.generic_ienumerator_type,
1184 +                               generic_args, Location);
1185 +                       list.Add (generic_enumerator_type);
1186 +
1187 +                       Bases = list;
1188 +
1189 +                       return base.GetClassBases (out base_class);
1190 +               }
1191 +
1192 +               protected override bool DoDefineMembers ()
1193 +               {
1194 +                       pc_field = CaptureVariable ("$PC", TypeManager.int32_type);
1195 +                       current_field = CaptureVariable ("$current", Iterator.OriginalIteratorType);
1196 +
1197 +                       Define_Current (true);
1198 +                       Define_Current (false);
1199 +                       dispose = new DisposeMethod (this);
1200 +                       Define_Reset ();
1201 +
1202 +                       if (Iterator.IsEnumerable) {
1203 +                               new GetEnumeratorMethod (this, false);
1204 +                               new GetEnumeratorMethod (this, true);
1205 +                       }
1206 +
1207 +                       if (!base.DoDefineMembers ())
1208 +                               return false;
1209 +
1210 +                       FetchMethodDispose ();
1211 +                       return true;
1212 +               }
1213 +
1214 +               protected override void EmitScopeConstructor (EmitContext ec)
1215 +               {
1216 +                       ec.ig.Emit (OpCodes.Ldarg_0);
1217 +                       ec.ig.Emit (OpCodes.Ldarg_1);
1218 +                       ec.ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);
1219 +                       base.EmitScopeConstructor (ec);
1220 +               }
1221 +
1222 +               void FetchMethodDispose ()
1223 +               {
1224 +                       MemberList dispose_list;
1225 +
1226 +                       dispose_list = FindMembers (
1227 +                               CurrentType != null ? CurrentType : TypeBuilder,
1228 +                               MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance,
1229 +                               Type.FilterName, "Dispose");
1230 +
1231 +                       if (dispose_list.Count != 1)
1232 +                               throw new InternalErrorException ("Cannot find Dipose() method.");
1233 +
1234 +                       dispose_method = (MethodInfo) dispose_list [0];
1235 +               }
1236 +
1237 +               void Define_Current (bool is_generic)
1238 +               {
1239 +                       MemberName left;
1240 +                       Expression type;
1241 +
1242 +                       if (is_generic) {
1243 +                               left = new MemberName (
1244 +                                       "System.Collections.Generic.IEnumerator",
1245 +                                       generic_args, Location);
1246 +                               type = iterator_type_expr;
1247 +                       } else {
1248 +                               left = new MemberName ("System.Collections.IEnumerator", Location);
1249 +                               type = TypeManager.system_object_expr;
1250 +                       }
1251 +
1252 +                       MemberName name = new MemberName (left, "Current", null, Location);
1253 +
1254 +                       ToplevelBlock get_block = new ToplevelBlock (Location);
1255 +                       get_block.AddStatement (new CurrentBlock (this, is_generic));
1256 +
1257 +                       Accessor getter = new Accessor (get_block, 0, null, Location);
1258 +
1259 +                       Property current = new Property (
1260 +                               this, type, 0, false, name, null, getter, null);
1261 +                       AddProperty (current);
1262 +               }
1263 +
1264 +               void Define_Reset ()
1265 +               {
1266 +                       Method reset = new Method (
1267 +                               this, null, TypeManager.system_void_expr, Modifiers.PUBLIC,
1268 +                               false, new MemberName ("Reset", Location),
1269 +                               Parameters.EmptyReadOnlyParameters, null);
1270 +                       AddMethod (reset);
1271 +
1272 +                       reset.Block = new ToplevelBlock (Location);
1273 +                       reset.Block.AddStatement (Create_ThrowNotSupported ());
1274 +               }
1275 +
1276 +               Statement Create_ThrowNotSupported ()
1277 +               {
1278 +                       TypeExpr ex_type = new TypeExpression (
1279 +                               TypeManager.not_supported_exception_type, Location);
1280 +
1281 +                       return new Throw (new New (ex_type, null, Location), Location);
1282 +               }
1283 +
1284 +               ConstructorInfo GetInvalidOperationException ()
1285 +               {
1286 +                       MethodGroupExpr mg = (MethodGroupExpr) Expression.MemberLookup (
1287 +                               TypeBuilder, TypeManager.invalid_operation_exception_type,
1288 +                               ".ctor", Location);
1289 +                       if (mg == null)
1290 +                               throw new InternalErrorException ();
1291 +                       return (ConstructorInfo) mg.Methods [0];
1292 +               }
1293 +
1294 +               MethodInfo GetCompareExchange ()
1295 +               {
1296 +                       MethodGroupExpr mg = (MethodGroupExpr) Expression.MemberLookup (
1297 +                               TypeBuilder, TypeManager.interlocked_type,
1298 +                               "CompareExchange", Location);
1299 +                       if (mg == null)
1300 +                               throw new InternalErrorException ();
1301 +                       return (MethodInfo) mg.Methods [0];
1302 +               }
1303 +
1304 +               protected override ScopeInitializerBase CreateScopeInitializer ()
1305 +               {
1306 +                       return new IteratorHostInitializer (this);
1307 +               }
1308 +
1309 +               protected class IteratorHostInitializer : AnonymousMethodHostInitializer
1310 +               {
1311 +                       new public readonly IteratorHost Host;
1312 +                       protected Iterator.State state;
1313 +
1314 +                       public IteratorHostInitializer (IteratorHost host)
1315 +                               : base (host)
1316 +                       {
1317 +                               this.Host = host;
1318 +                       }
1319 +
1320 +                       protected override bool DoResolveInternal (EmitContext ec)
1321 +                       {
1322 +                               if (this is EnumeratorScopeInitializer)
1323 +                                       state = Iterator.State.Running;
1324 +                               else if (Host.Iterator.IsEnumerable)
1325 +                                       state = Iterator.State.Uninitialized;
1326 +                               else
1327 +                                       state = Iterator.State.Running;
1328 +
1329 +                               return base.DoResolveInternal (ec);
1330 +                       }
1331 +
1332 +                       protected override void EmitScopeConstructor (EmitContext ec)
1333 +                       {
1334 +                               ec.ig.Emit (OpCodes.Ldc_I4, (int) state);
1335 +                               base.EmitScopeConstructor (ec);
1336 +                       }
1337 +               }
1338 +
1339 +               protected class GetEnumeratorMethod : Method
1340 +               {
1341 +                       public IteratorHost Host;
1342 +
1343 +                       static MemberName GetMemberName (IteratorHost host, bool is_generic)
1344 +                       {
1345 +                               MemberName left;
1346 +                               if (is_generic) {
1347 +                                       left = new MemberName (
1348 +                                               "System.Collections.Generic.IEnumerable",
1349 +                                               host.generic_args, host.Location);
1350 +                               } else {
1351 +                                       left = new MemberName (
1352 +                                               "System.Collections.IEnumerable", host.Location);
1353 +                               }
1354 +
1355 +                               return new MemberName (left, "GetEnumerator", host.Location);
1356 +                       }
1357 +
1358 +                       public GetEnumeratorMethod (IteratorHost host, bool is_generic)
1359 +                               : base (host, null, is_generic ?
1360 +                                       host.generic_enumerator_type : host.enumerator_type,
1361 +                                       0, false, GetMemberName (host, is_generic),
1362 +                                       Parameters.EmptyReadOnlyParameters, null)
1363 +                       {
1364 +                               this.Host = host;
1365 +
1366 +                               host.AddMethod (this);
1367 +
1368 +                               Block = new ToplevelBlock (host.Iterator.Container, null, Location);
1369 +                               Block.AddStatement (new GetEnumeratorStatement (host, Type, is_generic));
1370 +                       }
1371 +
1372 +                       public override EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
1373 +                       {
1374 +                               EmitContext ec = new EmitContext (
1375 +                                       this, tc, this.ds, Location, ig, MemberType, ModFlags, false);
1376 +
1377 +                               ec.CurrentAnonymousMethod = Host.Iterator;
1378 +                               return ec;
1379 +                       }
1380 +
1381 +                       protected class GetEnumeratorStatement : Statement
1382 +                       {
1383 +                               IteratorHost host;
1384 +                               Expression type;
1385 +                               bool is_generic;
1386 +
1387 +                               ExpressionStatement initializer;
1388 +                               Expression cast;
1389 +                               MethodInfo ce;
1390 +
1391 +                               public GetEnumeratorStatement (IteratorHost host, Expression type,
1392 +                                                              bool is_generic)
1393 +                               {
1394 +                                       this.host = host;
1395 +                                       this.type = type;
1396 +                                       this.is_generic = is_generic;
1397 +                                       loc = host.Location;
1398 +                               }
1399 +
1400 +                               public override bool Resolve (EmitContext ec)
1401 +                               {
1402 +                                       type = type.ResolveAsTypeTerminal (ec, false);
1403 +                                       if ((type == null) || (type.Type == null))
1404 +                                               return false;
1405 +
1406 +                                       initializer = host.GetEnumeratorInitializer (ec);
1407 +                                       if (initializer == null)
1408 +                                               return false;
1409 +
1410 +                                       cast = new ClassCast (initializer, type.Type);
1411 +
1412 +                                       ce = host.GetCompareExchange ();
1413 +
1414 +                                       ec.CurrentBranching.CurrentUsageVector.Return ();
1415 +                                       return true;
1416 +                               }
1417 +
1418 +                               protected override void DoEmit (EmitContext ec)
1419 +                               {
1420 +                                       ILGenerator ig = ec.ig;
1421 +                                       Label label_init = ig.DefineLabel ();
1422 +
1423 +                                       ig.Emit (OpCodes.Ldarg_0);
1424 +                                       ig.Emit (OpCodes.Ldflda, host.PC.FieldBuilder);
1425 +                                       ig.Emit (OpCodes.Ldc_I4, (int) Iterator.State.Running);
1426 +                                       ig.Emit (OpCodes.Ldc_I4, (int) Iterator.State.Uninitialized);
1427 +                                       ig.Emit (OpCodes.Call, ce);
1428 +
1429 +                                       ig.Emit (OpCodes.Ldc_I4, (int) Iterator.State.Uninitialized);
1430 +                                       ig.Emit (OpCodes.Bne_Un, label_init);
1431 +
1432 +                                       ig.Emit (OpCodes.Ldarg_0);
1433 +                                       ig.Emit (OpCodes.Ret);
1434 +
1435 +                                       ig.MarkLabel (label_init);
1436 +
1437 +                                       initializer.EmitStatement (ec);
1438 +                                       cast.Emit (ec);
1439 +                                       ig.Emit (OpCodes.Ret);
1440 +                               }
1441 +                       }
1442 +               }
1443 +
1444 +               protected class DisposeMethod : Method
1445 +               {
1446 +                       public IteratorHost Host;
1447 +
1448 +                       public DisposeMethod (IteratorHost host)
1449 +                               : base (host, null, TypeManager.system_void_expr, Modifiers.PUBLIC,
1450 +                                       false, new MemberName ("Dispose", host.Location),
1451 +                                       Parameters.EmptyReadOnlyParameters, null)
1452 +                       {
1453 +                               this.Host = host;
1454 +
1455 +                               host.AddMethod (this);
1456 +
1457 +                               Block = new ToplevelBlock (host.Iterator.Block, null, Location);
1458 +                               Block.AddStatement (new DisposeMethodStatement (Host.Iterator));
1459 +
1460 +                               Report.Debug (64, "DISPOSE METHOD", host, Block);
1461 +                       }
1462 +
1463 +                       public override EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
1464 +                       {
1465 +                               EmitContext ec = new EmitContext (
1466 +                                       this, tc, this.ds, Location, ig, MemberType, ModFlags, false);
1467 +
1468 +                               ec.CurrentAnonymousMethod = Host.Iterator;
1469 +                               return ec;
1470 +                       }
1471 +
1472 +                       protected class DisposeMethodStatement : Statement
1473 +                       {
1474 +                               Iterator iterator;
1475 +
1476 +                               public DisposeMethodStatement (Iterator iterator)
1477 +                               {
1478 +                                       this.iterator = iterator;
1479 +                                       this.loc = iterator.Location;
1480 +                               }
1481 +
1482 +                               public override bool Resolve (EmitContext ec)
1483 +                               {
1484 +                                       return true;
1485 +                               }
1486 +
1487 +                               protected override void DoEmit (EmitContext ec)
1488 +                               {
1489 +                                       iterator.EmitDispose (ec);
1490 +                               }
1491 +                       }
1492 +               }
1493 +
1494 +               protected ScopeInitializer GetEnumeratorInitializer (EmitContext ec)
1495 +               {
1496 +                       ScopeInitializer init = new EnumeratorScopeInitializer (this);
1497 +                       if (init.Resolve (ec) == null)
1498 +                               throw new InternalErrorException ();
1499 +                       return init;
1500 +               }
1501 +
1502 +               protected class EnumeratorScopeInitializer : IteratorHostInitializer
1503 +               {
1504 +                       IteratorHost host;
1505 +
1506 +                       public EnumeratorScopeInitializer (IteratorHost host)
1507 +                               : base (host)
1508 +                       {
1509 +                               this.host = host;
1510 +                       }
1511 +
1512 +                       protected override bool DoResolveInternal (EmitContext ec)
1513 +                       {
1514 +                               type = host.IsGeneric ? host.CurrentType : host.TypeBuilder;
1515 +                               return base.DoResolveInternal (ec);
1516 +                       }
1517 +
1518 +                       protected override void DoEmit (EmitContext ec)
1519 +                       {
1520 +                               DoEmitInstance (ec);
1521 +                       }
1522 +
1523 +                       protected override void EmitParameterReference (EmitContext ec,
1524 +                                                                       CapturedParameter cp)
1525 +                       {
1526 +                               ec.ig.Emit (OpCodes.Ldarg_0);
1527 +                               ec.ig.Emit (OpCodes.Ldfld, cp.Field.FieldBuilder);
1528 +                       }
1529 +               }
1530 +
1531 +               protected class CurrentBlock : Statement {
1532 +                       IteratorHost host;
1533 +                       bool is_generic;
1534 +
1535 +                       public CurrentBlock (IteratorHost host, bool is_generic)
1536 +                       {
1537 +                               this.host = host;
1538 +                               this.is_generic = is_generic;
1539 +                               loc = host.Location;
1540 +                       }
1541 +
1542 +                       public override bool Resolve (EmitContext ec)
1543 +                       {
1544 +                               ec.CurrentBranching.CurrentUsageVector.Return ();
1545 +                               return true;
1546 +                       }
1547 +
1548 +                       protected override void DoEmit (EmitContext ec)
1549 +                       {
1550 +                               ILGenerator ig = ec.ig;
1551 +                               Label label_ok = ig.DefineLabel ();
1552 +
1553 +                               ig.Emit (OpCodes.Ldarg_0);
1554 +                               ig.Emit (OpCodes.Ldfld, host.PC.FieldBuilder);
1555 +                               ig.Emit (OpCodes.Ldc_I4, (int) Iterator.State.Running);
1556 +                               ig.Emit (OpCodes.Bgt, label_ok);
1557 +
1558 +                               ig.Emit (OpCodes.Newobj, host.GetInvalidOperationException ());
1559 +                               ig.Emit (OpCodes.Throw);
1560 +
1561 +                               ig.MarkLabel (label_ok);
1562 +                               ig.Emit (OpCodes.Ldarg_0);
1563 +                               ig.Emit (OpCodes.Ldfld, host.CurrentField.FieldBuilder);
1564 +                               if (!is_generic)
1565 +                                       ig.Emit (OpCodes.Box, host.CurrentField.MemberType);
1566 +                               ig.Emit (OpCodes.Ret);
1567 +                       }
1568 +               }
1569 +       }
1570 +
1571 +       public class Iterator : AnonymousContainer {
1572 +               protected readonly ToplevelBlock OriginalBlock;
1573 +               protected readonly IMethodData OriginalMethod;
1574 +               protected ToplevelBlock block;
1575 +
1576 +               public readonly bool IsEnumerable;
1577                 public readonly bool IsStatic;
1578  
1579                 //
1580 @@ -139,7 +586,6 @@
1581                 // Context from the original method
1582                 //
1583                 GenericMethod generic_method;
1584 -               TypeContainer container;
1585                 TypeExpr current_type;
1586                 Type this_type;
1587                 Parameters parameters;
1588 @@ -147,34 +593,33 @@
1589                 IMethodData orig_method;
1590  
1591                 MethodInfo dispose_method;
1592 -               MoveNextMethod move_next_method;
1593 +               Method move_next_method;
1594                 Constructor ctor;
1595 -               CaptureContext cc;
1596  
1597                 Expression enumerator_type;
1598                 Expression enumerable_type;
1599                 Expression generic_enumerator_type;
1600                 Expression generic_enumerable_type;
1601                 TypeArguments generic_args;
1602 -               EmitContext ec;
1603  
1604 -               protected enum State {
1605 +               public readonly Type OriginalIteratorType;
1606 +               public readonly IteratorHost IteratorHost;
1607 +
1608 +               public enum State {
1609                         Uninitialized   = -2,
1610                         After,
1611                         Running
1612                 }
1613  
1614 -               static int proxy_count;
1615 -
1616                 public void EmitYieldBreak (ILGenerator ig)
1617                 {
1618                         ig.Emit (OpCodes.Ldarg_0);
1619                         IntConstant.EmitInt (ig, (int) State.After);
1620 -                       ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);
1621 +                       ig.Emit (OpCodes.Stfld, IteratorHost.PC.FieldBuilder);
1622                         ig.Emit (OpCodes.Br, move_next_error);
1623                 }
1624  
1625 -               public void EmitMoveNext (EmitContext ec)
1626 +               internal void EmitMoveNext (EmitContext ec, Block original_block)
1627                 {
1628                         ILGenerator ig = ec.ig;
1629  
1630 @@ -192,7 +637,7 @@
1631                         resume_points.Add (entry_point);
1632                         entry_point.Define (ig);
1633  
1634 -                       ec.EmitTopBlock (orig_method, original_block);
1635 +                       original_block.Emit (ec);
1636  
1637                         EmitYieldBreak (ig);
1638  
1639 @@ -203,7 +648,7 @@
1640                                 labels [i] = ((ResumePoint) resume_points [i]).Label;
1641  
1642                         ig.Emit (OpCodes.Ldarg_0);
1643 -                       ig.Emit (OpCodes.Ldfld, pc_field.FieldBuilder);
1644 +                       ig.Emit (OpCodes.Ldfld, IteratorHost.PC.FieldBuilder);
1645                         ig.Emit (OpCodes.Switch, labels);
1646  
1647                         Label end = ig.DefineLabel ();
1648 @@ -221,7 +666,7 @@
1649                         ig.BeginFaultBlock ();
1650  
1651                         ig.Emit (OpCodes.Ldarg_0);
1652 -                       ig.Emit (OpCodes.Callvirt, dispose_method);
1653 +                       ig.Emit (OpCodes.Callvirt, IteratorHost.Dispose);
1654  
1655                         ig.EndExceptionBlock ();
1656  
1657 @@ -264,12 +709,12 @@
1658  
1659                         ig.MarkLabel (dispatcher);
1660                         ig.Emit (OpCodes.Ldarg_0);
1661 -                       ig.Emit (OpCodes.Ldfld, pc_field.FieldBuilder);
1662 +                       ig.Emit (OpCodes.Ldfld, IteratorHost.PC.FieldBuilder);
1663                         ig.Emit (OpCodes.Switch, labels);
1664  
1665                         ig.Emit (OpCodes.Ldarg_0);
1666                         IntConstant.EmitInt (ig, (int) State.After);
1667 -                       ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);
1668 +                       ig.Emit (OpCodes.Stfld, IteratorHost.PC.FieldBuilder);
1669  
1670                         ig.MarkLabel (end);
1671                 }
1672 @@ -305,13 +750,13 @@
1673                         // Store the new current
1674                         ig.Emit (OpCodes.Ldarg_0);
1675                         expr.Emit (ec);
1676 -                       ig.Emit (OpCodes.Stfld, current_field.FieldBuilder);
1677 +                       ig.Emit (OpCodes.Stfld, IteratorHost.CurrentField.FieldBuilder);
1678  
1679                         // increment pc
1680                         pc++;
1681                         ig.Emit (OpCodes.Ldarg_0);
1682                         IntConstant.EmitInt (ig, pc);
1683 -                       ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);
1684 +                       ig.Emit (OpCodes.Stfld, IteratorHost.PC.FieldBuilder);
1685  
1686                         // Return ok
1687                         ig.Emit (OpCodes.Br, move_next_ok);
1688 @@ -329,728 +774,94 @@
1689                         pc++;
1690                         ig.Emit (OpCodes.Ldarg_0);
1691                         IntConstant.EmitInt (ig, pc);
1692 -                       ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);
1693 +                       ig.Emit (OpCodes.Stfld, IteratorHost.PC.FieldBuilder);
1694  
1695                         ResumePoint point = new ResumePoint (finally_blocks);
1696                         resume_points.Add (point);
1697                         point.Define (ig);
1698                 }
1699  
1700 -               private static MemberName MakeProxyName (string name, GenericMethod generic, Location loc)
1701 -               {
1702 -                       int pos = name.LastIndexOf ('.');
1703 -                       if (pos > 0)
1704 -                               name = name.Substring (pos + 1);
1705 +               public override bool IsIterator {
1706 +                       get { return true; }
1707 +               }
1708  
1709 -                       string proxy_name = "<" + name + ">__" + (proxy_count++);
1710 -
1711 -                       if (generic != null) {
1712 -                               TypeArguments args = new TypeArguments (loc);
1713 -                               foreach (TypeParameter tparam in generic.CurrentTypeParameters)
1714 -                                       args.Add (new SimpleName (tparam.Name, loc));
1715 -                               return new MemberName (proxy_name, args, loc);
1716 -                       } else
1717 -                               return new MemberName (proxy_name, loc);
1718 +               public override AnonymousMethodHost RootScope {
1719 +                       get { return IteratorHost; }
1720                 }
1721  
1722                 //
1723                 // Our constructor
1724                 //
1725 -               public Iterator (IMethodData m_container, DeclSpace parent, GenericMethod generic,
1726 -                                int modifiers)
1727 -                       : base (parent.NamespaceEntry, parent,
1728 -                               MakeProxyName (m_container.MethodName.Name, generic, m_container.Location),
1729 -                               (modifiers & Modifiers.UNSAFE) | Modifiers.PRIVATE, null)
1730 +               public Iterator (IMethodData m_container, TypeContainer host, GenericMethod generic,
1731 +                                ToplevelBlock container, ToplevelBlock block, int modifiers,
1732 +                                Type iterator_type, bool is_enumerable)
1733 +                       : base (null, host, generic, m_container.ParameterInfo,
1734 +                               block, m_container.Block, TypeManager.bool_type, modifiers,
1735 +                               m_container.Location)
1736                 {
1737 -                       this.orig_method = m_container;
1738 +                       this.OriginalBlock = m_container.Block;
1739 +                       this.OriginalMethod = m_container;
1740 +                       this.OriginalIteratorType = iterator_type;
1741 +                       this.IsEnumerable = is_enumerable;
1742  
1743 -                       this.generic_method = generic;
1744 -                       this.container = ((TypeContainer) parent).PartialContainer;
1745 -                       this.original_parameters = m_container.ParameterInfo;
1746 -                       this.original_block = orig_method.Block;
1747 -                       this.block = new ToplevelBlock (orig_method.Block, parameters, orig_method.Location);
1748 +                       Report.Debug (64, "NEW ITERATOR", host, generic, OriginalBlock,
1749 +                                     Container, Block, block);
1750  
1751 -                       if (generic != null) {
1752 -                               ArrayList constraints = new ArrayList ();
1753 -                               foreach (TypeParameter tparam in generic.TypeParameters)
1754 -                                       constraints.Add (tparam.Constraints);
1755 +                       IteratorHost = new IteratorHost (this);
1756 +                       Block.CreateIteratorHost (IteratorHost);
1757  
1758 -                               SetParameterInfo (constraints);
1759 -                       }
1760 +                       OriginalBlock.ReParent (Container);
1761  
1762 -                       IsStatic = (modifiers & Modifiers.STATIC) != 0;
1763 -               }
1764 +                       m_container.Block = block;
1765  
1766 -               public AnonymousContainer Host {
1767 -                       get { return move_next_method; }
1768 +                       OriginalBlock.MakeIterator (this);
1769                 }
1770  
1771 -               public bool DefineIterator ()
1772 +               protected class TestStatement : Statement
1773                 {
1774 -                       ec = new EmitContext (this, this, Location, null, null, ModFlags);
1775 -                       ec.CurrentAnonymousMethod = move_next_method;
1776 -                       ec.InIterator = true;
1777 -
1778 -                       if (!CheckType ()) {
1779 -                               Report.Error (1624, Location,
1780 -                                       "The body of `{0}' cannot be an iterator block because `{1}' is not an iterator interface type",
1781 -                                       orig_method.GetSignatureForError (), TypeManager.CSharpName (orig_method.ReturnType));
1782 -                               return false;
1783 +                       public override bool Resolve (EmitContext ec)
1784 +                       {
1785 +                               return true;
1786                         }
1787  
1788 -                       for (int i = 0; i < original_parameters.Count; i++){
1789 -                               Parameter.Modifier mod = original_parameters.ParameterModifier (i);
1790 -                               if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0){
1791 -                                       Report.Error (
1792 -                                               1623, Location,
1793 -                                               "Iterators cannot have ref or out parameters");
1794 -                                       return false;
1795 -                               }
1796 -
1797 -                               if ((mod & Parameter.Modifier.ARGLIST) != 0) {
1798 -                                       Report.Error (1636, Location, "__arglist is not allowed in parameter list of iterators");
1799 -                                       return false;
1800 -                               }
1801 -
1802 -                               if (original_parameters.ParameterType (i).IsPointer) {
1803 -                                       Report.Error (1637, Location, "Iterators cannot have unsafe parameters or yield types");
1804 -                                       return false;
1805 -                               }
1806 +                       protected override void DoEmit (EmitContext ec)
1807 +                       {
1808 +                               ec.ig.Emit (OpCodes.Nop);
1809 +                               ec.ig.Emit (OpCodes.Neg);
1810 +                               ec.ig.Emit (OpCodes.Pop);
1811 +                               ec.ig.Emit (OpCodes.Ret);
1812                         }
1813 -
1814 -                       if (container.CurrentType != null)
1815 -                               this_type = container.CurrentType;
1816 -                       else
1817 -                               this_type = container.TypeBuilder;
1818 -
1819 -                       container.AddIterator (this);
1820 -
1821 -                       orig_method.Block = block;
1822 -                       return true;
1823                 }
1824  
1825 -               MethodInfo FetchMethodDispose ()
1826 +               public override bool Resolve (EmitContext ec)
1827                 {
1828 -                       MemberList dispose_list;
1829 +                       Report.Debug (64, "RESOLVE ITERATOR", this, Container, Block);
1830  
1831 -                       dispose_list = FindMembers (
1832 -                               current_type.Type,
1833 -                               MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance,
1834 -                               Type.FilterName, "Dispose");
1835 -
1836 -                       if (dispose_list.Count != 1)
1837 -                               throw new InternalErrorException ("Cannot find Dipose() method.");
1838 -
1839 -                       return (MethodInfo) dispose_list [0];
1840 -               }
1841 -
1842 -               protected override bool DoDefineMembers ()
1843 -               {
1844 -                       ec.InIterator = true;
1845 -                       ec.CurrentAnonymousMethod = move_next_method;
1846 -                       ec.capture_context = cc;
1847 -
1848 -                       if (!base.DoDefineMembers ())
1849 +                       if (!base.Resolve (ec))
1850                                 return false;
1851  
1852 -                       dispose_method = FetchMethodDispose ();
1853 -                       if (dispose_method == null)
1854 -                               return false;
1855 +                       Report.Debug (64, "RESOLVE ITERATOR #1", this, method, method.Parent,
1856 +                                     RootScope, ec);
1857  
1858 -                       return true;
1859 -               }
1860 -
1861 -               public override bool Define ()
1862 -               {
1863 -                       if (!base.Define ())
1864 +                       if (!RootScope.DefineMembers ())
1865                                 return false;
1866  
1867 -                       ec.InIterator = true;
1868 -                       ec.CurrentAnonymousMethod = move_next_method;
1869 -                       ec.capture_context = cc;
1870 +                       ExpressionStatement scope_init = RootScope.GetScopeInitializer (ec);
1871 +                       Container.AddStatement (new StatementExpression (scope_init));
1872 +                       Expression cast = new ClassCast (scope_init, OriginalMethod.ReturnType);
1873 +                       Container.AddStatement (new NoCheckReturn (cast));
1874  
1875 -                       ec.TypeContainer = ec.TypeContainer.Parent;
1876 -
1877 -                       if (ec.TypeContainer.CurrentType != null)
1878 -                               ec.ContainerType = ec.TypeContainer.CurrentType;
1879 -                       else
1880 -                               ec.ContainerType = ec.TypeContainer.TypeBuilder;
1881 -
1882 -                       ec.ig = move_next_method.method.MethodBuilder.GetILGenerator ();
1883 -
1884 -                       if (!ctor.Define ())
1885 -                               return false;
1886 -
1887 -                       bool unreachable;
1888 -
1889 -                       if (!ec.ResolveTopBlock (null, original_block, parameters, orig_method, out unreachable))
1890 -                               return false;
1891 -
1892 -                       if (!ec.ResolveTopBlock (null, block, parameters, orig_method, out unreachable))
1893 -                               return false;
1894 -
1895 -                       original_block.CompleteContexts ();
1896 -
1897 -                       cc.EmitAnonymousHelperClasses (ec);
1898 -
1899                         return true;
1900                 }
1901  
1902 -               TypeExpr InflateType (Type it)
1903 +               protected override Method DoCreateMethodHost (EmitContext ec)
1904                 {
1905 -                       if (generic_method == null)
1906 -                               return new TypeExpression (it, Location);
1907 -
1908 -                       if (it.IsGenericParameter && (it.DeclaringMethod != null)) {
1909 -                               int pos = it.GenericParameterPosition;
1910 -                               it = CurrentTypeParameters [pos].Type;
1911 -                       } else if (it.IsGenericType) {
1912 -                               Type[] args = it.GetGenericArguments ();
1913 -
1914 -                               TypeArguments inflated = new TypeArguments (Location);
1915 -                               foreach (Type t in args)
1916 -                                       inflated.Add (InflateType (t));
1917 -
1918 -                               return new ConstructedType (it, inflated, Location);
1919 -                       } else if (it.IsArray) {
1920 -                               TypeExpr et_expr = InflateType (it.GetElementType ());
1921 -                               int rank = it.GetArrayRank ();
1922 -
1923 -                               Type et = et_expr.ResolveAsTypeTerminal (ec, false).Type;
1924 -                               it = et.MakeArrayType (rank);
1925 -                       }
1926 -
1927 -                       return new TypeExpression (it, Location);
1928 +                       return new AnonymousMethodMethod (
1929 +                               this, null, TypeManager.system_boolean_expr,
1930 +                               Modifiers.PUBLIC, new MemberName ("MoveNext", Location),
1931 +                               Parameters.EmptyReadOnlyParameters);
1932                 }
1933  
1934 -               Parameter InflateParameter (Parameter param)
1935 -               {
1936 -                       TypeExpr te = InflateType (param.ParameterType);
1937 -                       return new Parameter (
1938 -                               te, param.Name, param.ModFlags, param.OptAttributes, param.Location);
1939 -               }
1940 -
1941 -               Parameters InflateParameters (Parameters parameters, EmitContext ec)
1942 -               {
1943 -                       int count = parameters.FixedParameters.Length;
1944 -                       if (count == 0)
1945 -                               return Parameters.EmptyReadOnlyParameters;
1946 -                       Parameter[] fixed_params = new Parameter [count];
1947 -                       for (int i = 0; i < count; i++)
1948 -                               fixed_params [i] = InflateParameter (parameters.FixedParameters [i]);
1949 -
1950 -                       return new Parameters (fixed_params, parameters.HasArglist);
1951 -               }
1952 -
1953 -               public override TypeExpr [] GetClassBases (out TypeExpr base_class)
1954 -               {
1955 -                       iterator_type_expr = InflateType (original_iterator_type);
1956 -
1957 -                       generic_args = new TypeArguments (Location);
1958 -                       generic_args.Add (iterator_type_expr);
1959 -
1960 -                       ArrayList list = new ArrayList ();
1961 -                       if (is_enumerable) {
1962 -                               enumerable_type = new TypeExpression (
1963 -                                       TypeManager.ienumerable_type, Location);
1964 -                               list.Add (enumerable_type);
1965 -
1966 -                               generic_enumerable_type = new ConstructedType (
1967 -                                       TypeManager.generic_ienumerable_type,
1968 -                                       generic_args, Location);
1969 -                               list.Add (generic_enumerable_type);
1970 -                       }
1971 -
1972 -                       enumerator_type = new TypeExpression (
1973 -                               TypeManager.ienumerator_type, Location);
1974 -                       list.Add (enumerator_type);
1975 -
1976 -                       list.Add (new TypeExpression (TypeManager.idisposable_type, Location));
1977 -
1978 -                       generic_enumerator_type = new ConstructedType (
1979 -                               TypeManager.generic_ienumerator_type,
1980 -                               generic_args, Location);
1981 -                       list.Add (generic_enumerator_type);
1982 -
1983 -                       Bases = list;
1984 -
1985 -                       return base.GetClassBases (out base_class);
1986 -               }
1987 -
1988 -               //
1989 -               // Returns the new block for the method, or null on failure
1990 -               //
1991 -               protected override bool DefineNestedTypes ()
1992 -               {
1993 -                       if (CurrentType != null)
1994 -                               current_type = new TypeExpression (CurrentType, Location);
1995 -                       else
1996 -                               current_type = new TypeExpression (TypeBuilder, Location);
1997 -
1998 -                       if (IsGeneric) {
1999 -                               foreach (TypeParameter tparam in TypeParameters)
2000 -                                       tparam.InflateConstraints (current_type.Type);
2001 -                       }
2002 -
2003 -                       parameters = InflateParameters (original_parameters, ec);
2004 -                       if (!parameters.Resolve (ec)) {
2005 -                               // TODO:
2006 -                       }
2007 -
2008 -                       Define_Fields ();
2009 -                       Define_Current (false);
2010 -                       Define_Current (true);
2011 -                       Define_MoveNext ();
2012 -                       Define_Reset ();
2013 -                       Define_Dispose ();
2014 -
2015 -                       Define_Constructor ();
2016 -
2017 -                       Create_Block ();
2018 -
2019 -                       if (is_enumerable) {
2020 -                               Define_GetEnumerator (false);
2021 -                               Define_GetEnumerator (true);
2022 -                       }
2023 -
2024 -                       return base.DefineNestedTypes ();
2025 -               }
2026 -
2027 -               Field pc_field;
2028 -               Field current_field;
2029 -               Method dispose;
2030 -
2031 -               void Create_Block ()
2032 -               {
2033 -                       original_block.SetHaveAnonymousMethods (Location, move_next_method);
2034 -                       block.SetHaveAnonymousMethods (Location, move_next_method);
2035 -
2036 -                       cc = original_block.CaptureContext;
2037 -
2038 -                       int first = IsStatic ? 0 : 1;
2039 -
2040 -                       ArrayList args = new ArrayList ();
2041 -                       if (!IsStatic) {
2042 -                               Type t = this_type;
2043 -                               args.Add (new Argument (
2044 -                                       new ThisParameterReference (t, Location)));
2045 -                               cc.CaptureThis (move_next_method);
2046 -                       }
2047 -
2048 -                       args.Add (new Argument (new BoolLiteral (false, Location)));
2049 -
2050 -                       for (int i = 0; i < parameters.Count; i++) {
2051 -                               Type t = original_parameters.ParameterType (i);
2052 -                               Type inflated = parameters.ParameterType (i);
2053 -                               string name = parameters.ParameterName (i);
2054 -
2055 -                               args.Add (new Argument (
2056 -                                       new SimpleParameterReference (t, first + i, Location)));
2057 -
2058 -                               cc.AddParameterToContext (move_next_method, name, inflated, first + i);
2059 -                       }
2060 -
2061 -                       TypeExpr proxy_type;
2062 -                       if (generic_method != null) {
2063 -                               TypeArguments new_args = new TypeArguments (Location);
2064 -                               if (Parent.IsGeneric) {
2065 -                                       foreach (TypeParameter tparam in Parent.TypeParameters)
2066 -                                               new_args.Add (new TypeParameterExpr (tparam, Location));
2067 -                               }
2068 -                               foreach (TypeParameter tparam in generic_method.TypeParameters)
2069 -                                       new_args.Add (new TypeParameterExpr (tparam, Location));
2070 -                               ConstructedType ct = new ConstructedType (CurrentType, new_args, Location);
2071 -                               proxy_type = ct.ResolveAsTypeTerminal (ec, false);
2072 -                       } else
2073 -                               proxy_type = current_type;
2074 -
2075 -                       Expression new_expr = new New (proxy_type, args, Location);
2076 -                       block.AddStatement (new NoCheckReturn (new_expr, Location));
2077 -               }
2078 -
2079 -               void Define_Fields ()
2080 -               {
2081 -                       pc_field = new Field (
2082 -                               this, TypeManager.system_int32_expr, Modifiers.PRIVATE, "$PC",
2083 -                               null, Location);
2084 -                       AddField (pc_field);
2085 -
2086 -                       current_field = new Field (
2087 -                               this, iterator_type_expr, Modifiers.PRIVATE, "$current",
2088 -                               null, Location);
2089 -                       AddField (current_field);
2090 -               }
2091 -
2092 -               void Define_Constructor ()
2093 -               {
2094 -                       Parameters ctor_params;
2095 -
2096 -                       ArrayList list = new ArrayList ();
2097 -
2098 -                       if (!IsStatic)
2099 -                               list.Add (new Parameter (
2100 -                                       new TypeExpression (this_type, Location),
2101 -                                       "this", Parameter.Modifier.NONE,
2102 -                                       null, Location));
2103 -                       list.Add (new Parameter (
2104 -                               TypeManager.bool_type, "initialized",
2105 -                               Parameter.Modifier.NONE, null, Location));
2106 -
2107 -                       Parameter[] old_fixed = parameters.FixedParameters;
2108 -                       list.AddRange (old_fixed);
2109 -
2110 -                       Parameter[] fixed_params = new Parameter [list.Count];
2111 -                       list.CopyTo (fixed_params);
2112 -
2113 -                       ctor_params = new Parameters (fixed_params);
2114 -
2115 -                       ctor = new Constructor (
2116 -                               this, MemberName.Name, Modifiers.PUBLIC, ctor_params,
2117 -                               new GeneratedBaseInitializer (Location),
2118 -                               Location);
2119 -                       AddConstructor (ctor);
2120 -
2121 -                       ctor.Block = new ToplevelBlock (block, parameters, Location);
2122 -
2123 -                       int first = IsStatic ? 2 : 3;
2124 -
2125 -                       State initial = is_enumerable ? State.Uninitialized : State.Running;
2126 -                       ctor.Block.AddStatement (new SetState (this, initial, Location));
2127 -
2128 -                       ctor.Block.AddStatement (new If (
2129 -                               new SimpleParameterReference (
2130 -                                       TypeManager.bool_type, first - 1, Location),
2131 -                               new SetState (this, State.Running, Location),
2132 -                               Location));
2133 -
2134 -                       ctor.Block.AddStatement (new InitScope (this, Location));
2135 -               }
2136 -
2137 -               Statement Create_ThrowInvalidOperation ()
2138 -               {
2139 -                       TypeExpr ex_type = new TypeExpression (
2140 -                               TypeManager.invalid_operation_exception_type, Location);
2141 -
2142 -                       return new Throw (new New (ex_type, null, Location), Location);
2143 -               }
2144 -
2145 -               Statement Create_ThrowNotSupported ()
2146 -               {
2147 -                       TypeExpr ex_type = new TypeExpression (
2148 -                               TypeManager.not_supported_exception_type, Location);
2149 -
2150 -                       return new Throw (new New (ex_type, null, Location), Location);
2151 -               }
2152 -
2153 -               void Define_Current (bool is_generic)
2154 -               {
2155 -                       MemberName left;
2156 -                       Expression type;
2157 -                       if (is_generic) {
2158 -                               left = new MemberName (
2159 -                                       "System.Collections.Generic.IEnumerator",
2160 -                                       generic_args, Location);
2161 -                               type = iterator_type_expr;
2162 -                       } else {
2163 -                               left = new MemberName ("System.Collections.IEnumerator", Location);
2164 -                               type = TypeManager.system_object_expr;
2165 -                       }
2166 -
2167 -                       MemberName name = new MemberName (left, "Current", null, Location);
2168 -
2169 -                       ToplevelBlock get_block = new ToplevelBlock (
2170 -                               block, parameters, Location);
2171 -
2172 -                       get_block.AddStatement (new If (
2173 -                               new Binary (
2174 -                                       Binary.Operator.LessThanOrEqual,
2175 -                                       new FieldExpression (this, pc_field),
2176 -                                       new IntLiteral ((int) State.Running, pc_field.Location)),
2177 -                               Create_ThrowInvalidOperation (),
2178 -                               new Return (
2179 -                                       new FieldExpression (this, current_field), Location),
2180 -                               Location));
2181 -
2182 -                       Accessor getter = new Accessor (get_block, 0, null, Location);
2183 -
2184 -                       Property current = new Property (
2185 -                               this, type, 0, false, name, null, getter, null);
2186 -                       AddProperty (current);
2187 -               }
2188 -
2189 -               void Define_MoveNext ()
2190 -               {
2191 -                       move_next_method = new MoveNextMethod (this, Location);
2192 -
2193 -                       original_block.ReParent (block, move_next_method);
2194 -
2195 -                       move_next_method.CreateMethod (ec);
2196 -
2197 -                       AddMethod (move_next_method.method);
2198 -               }
2199 -
2200 -               void Define_GetEnumerator (bool is_generic)
2201 -               {
2202 -                       MemberName left;
2203 -                       Expression type;
2204 -                       if (is_generic) {
2205 -                               left = new MemberName (
2206 -                                       "System.Collections.Generic.IEnumerable",
2207 -                                       generic_args, Location);
2208 -                               type = generic_enumerator_type;
2209 -                       } else {
2210 -                               left = new MemberName ("System.Collections.IEnumerable", Location);
2211 -                               type = enumerator_type;
2212 -                       }
2213 -
2214 -                       MemberName name = new MemberName (left, "GetEnumerator", Location);
2215 -
2216 -                       Method get_enumerator = new Method (
2217 -                               this, null, type, 0, false, name,
2218 -                               Parameters.EmptyReadOnlyParameters, null);
2219 -
2220 -                       //
2221 -                       // We call append instead of add, as we need to make sure that
2222 -                       // this method is resolved after the MoveNext method, as that one
2223 -                       // triggers the computation of the AnonymousMethod Scope, which is
2224 -                       // required during the code generation of the enumerator
2225 -                       //
2226 -                       AppendMethod (get_enumerator);
2227 -
2228 -                       get_enumerator.Block = new ToplevelBlock (
2229 -                               block, parameters, Location);
2230 -
2231 -                       get_enumerator.Block.SetHaveAnonymousMethods (Location, move_next_method);
2232 -
2233 -                       Expression ce = new MemberAccess (
2234 -                               new SimpleName ("System.Threading.Interlocked", Location),
2235 -                               "CompareExchange");
2236 -
2237 -                       Expression pc = new FieldExpression (this, pc_field);
2238 -                       Expression before = new IntLiteral ((int) State.Running, Location);
2239 -                       Expression uninitialized = new IntLiteral ((int) State.Uninitialized, Location);
2240 -
2241 -                       ArrayList args = new ArrayList ();
2242 -                       args.Add (new Argument (pc, Argument.AType.Ref));
2243 -                       args.Add (new Argument (before, Argument.AType.Expression));
2244 -                       args.Add (new Argument (uninitialized, Argument.AType.Expression));
2245 -
2246 -                       get_enumerator.Block.AddStatement (new If (
2247 -                               new Binary (
2248 -                                       Binary.Operator.Equality,
2249 -                                       new Invocation (ce, args),
2250 -                                       uninitialized),
2251 -                               new Return (new ThisParameterReference (type.Type, Location),
2252 -                                           Location),
2253 -                               Location));
2254 -
2255 -                       args = new ArrayList ();
2256 -                       if (!IsStatic) {
2257 -                               args.Add (new Argument (new CapturedThisReference (this, Location)));
2258 -                       }
2259 -
2260 -                       args.Add (new Argument (new BoolLiteral (true, Location)));
2261 -
2262 -                       for (int i = 0; i < parameters.Count; i++) {
2263 -                               Expression cp = new CapturedParameterReference (
2264 -                                       this, parameters.ParameterType (i),
2265 -                                       parameters.ParameterName (i), Location);
2266 -                               args.Add (new Argument (cp));
2267 -                       }
2268 -
2269 -                       Expression new_expr = new New (current_type, args, Location);
2270 -                       get_enumerator.Block.AddStatement (new Return (new_expr, Location));
2271 -               }
2272 -
2273 -               protected class SimpleParameterReference : Expression
2274 -               {
2275 -                       int idx;
2276 -
2277 -                       public SimpleParameterReference (Type type, int idx, Location loc)
2278 -                       {
2279 -                               this.idx = idx;
2280 -                               this.loc = loc;
2281 -                               this.type = type;
2282 -                               eclass = ExprClass.Variable;
2283 -                       }
2284 -
2285 -                       public override Expression DoResolve (EmitContext ec)
2286 -                       {
2287 -                               return this;
2288 -                       }
2289 -
2290 -                       public override void Emit (EmitContext ec)
2291 -                       {
2292 -                               DoEmit (ec);
2293 -                       }
2294 -
2295 -                       protected virtual void DoEmit (EmitContext ec)
2296 -                       {
2297 -                               ParameterReference.EmitLdArg (ec.ig, idx);
2298 -                       }
2299 -               }
2300 -
2301 -               protected class ThisParameterReference : SimpleParameterReference, IMemoryLocation
2302 -               {
2303 -                       public ThisParameterReference (Type type, Location loc)
2304 -                               : base (type, 0, loc)
2305 -                       { }
2306 -
2307 -                       protected override void DoEmit (EmitContext ec)
2308 -                       {
2309 -                               base.DoEmit (ec);
2310 -                               if (ec.TypeContainer is Struct)
2311 -                                       ec.ig.Emit (OpCodes.Ldobj, type);
2312 -                       }
2313 -
2314 -                       public void AddressOf (EmitContext ec, AddressOp mode)
2315 -                       {
2316 -                               if (ec.TypeContainer is Struct)
2317 -                                       ec.ig.Emit (OpCodes.Ldarga, 0);
2318 -                               else
2319 -                                       ec.ig.Emit (OpCodes.Ldarg, 0);
2320 -                       }
2321 -               }
2322 -
2323 -               protected class CapturedParameterReference : Expression
2324 -               {
2325 -                       Iterator iterator;
2326 -                       string name;
2327 -
2328 -                       public CapturedParameterReference (Iterator iterator, Type type,
2329 -                                                          string name, Location loc)
2330 -                       {
2331 -                               this.iterator = iterator;
2332 -                               this.loc = loc;
2333 -                               this.type = type;
2334 -                               this.name = name;
2335 -                               eclass = ExprClass.Variable;
2336 -                       }
2337 -
2338 -                       public override Expression DoResolve (EmitContext ec)
2339 -                       {
2340 -                               return this;
2341 -                       }
2342 -
2343 -                       public override void Emit (EmitContext ec)
2344 -                       {
2345 -                               ec.CurrentAnonymousMethod = iterator.move_next_method;
2346 -
2347 -                               LocalTemporary dummy = null;
2348 -                               
2349 -                               iterator.cc.EmitParameter (ec, name, false, false, ref dummy);
2350 -                       }
2351 -               }
2352 -
2353 -               protected class CapturedThisReference : Expression
2354 -               {
2355 -                       public CapturedThisReference (Iterator iterator, Location loc)
2356 -                       {
2357 -                               this.loc = loc;
2358 -                               this.type = iterator.this_type;
2359 -                               eclass = ExprClass.Variable;
2360 -                       }
2361 -
2362 -                       public override Expression DoResolve (EmitContext ec)
2363 -                       {
2364 -                               return this;
2365 -                       }
2366 -
2367 -                       public override void Emit (EmitContext ec)
2368 -                       {
2369 -                               ec.EmitThis (false);
2370 -                       }
2371 -               }
2372 -
2373 -               protected class FieldExpression : Expression
2374 -               {
2375 -                       Iterator iterator;
2376 -                       Field field;
2377 -
2378 -                       public FieldExpression (Iterator iterator, Field field)
2379 -                       {
2380 -                               this.iterator = iterator;
2381 -                               this.field = field;
2382 -                               this.loc = iterator.Location;
2383 -                       }
2384 -
2385 -                       public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
2386 -                       {
2387 -                               FieldExpr fexpr = new FieldExpr (field.FieldBuilder, loc);
2388 -                               fexpr.InstanceExpression = new ThisParameterReference (
2389 -                                       iterator.this_type, loc);
2390 -                               return fexpr.ResolveLValue (ec, right_side, loc);
2391 -                       }
2392 -
2393 -                       public override Expression DoResolve (EmitContext ec)
2394 -                       {
2395 -                               FieldExpr fexpr = new FieldExpr (field.FieldBuilder, loc);
2396 -                               fexpr.InstanceExpression = new ThisParameterReference (
2397 -                                       iterator.this_type, loc);
2398 -                               return fexpr.Resolve (ec);
2399 -                       }
2400 -
2401 -                       public override void Emit (EmitContext ec)
2402 -                       {
2403 -                               throw new InvalidOperationException ();
2404 -                       }
2405 -               }
2406 -
2407 -               protected class MoveNextMethod : AnonymousContainer
2408 -               {
2409 -                       Iterator iterator;
2410 -
2411 -                       public MoveNextMethod (Iterator iterator, Location loc)
2412 -                               : base (iterator.parameters, iterator.original_block, loc)
2413 -                       {
2414 -                               this.iterator = iterator;
2415 -                       }
2416 -
2417 -                       protected override bool CreateMethodHost (EmitContext ec)
2418 -                       {
2419 -                               method = new Method (
2420 -                                       iterator, null, TypeManager.system_boolean_expr,
2421 -                                       Modifiers.PUBLIC, false, new MemberName ("MoveNext", loc),
2422 -                                       Parameters.EmptyReadOnlyParameters, null);
2423 -
2424 -                               method.Block = Block;
2425 -
2426 -                               MoveNextStatement inline = new MoveNextStatement (iterator, loc);
2427 -                               Block.AddStatement (inline);
2428 -
2429 -                               return true;
2430 -                       }
2431 -
2432 -                       public bool CreateMethod (EmitContext ec)
2433 -                       {
2434 -                               return CreateMethodHost (ec);
2435 -                       }
2436 -
2437 -                       public override Iterator Iterator {
2438 -                               get { return iterator; }
2439 -                       }
2440 -
2441 -                       public void ComputeHost ()
2442 -                       {
2443 -                               ComputeMethodHost ();
2444 -                       }
2445 -                       
2446 -                       public override bool IsIterator {
2447 -                               get { return true; }
2448 -                       }
2449 -
2450 -                       public override void CreateScopeType (EmitContext ec, ScopeInfo scope)
2451 -                       {
2452 -                               scope.ScopeTypeBuilder = iterator.TypeBuilder;
2453 -                               scope.ScopeConstructor = iterator.ctor.ConstructorBuilder;
2454 -                       }
2455 -
2456 -                       public override void Emit (EmitContext ec)
2457 -                       {
2458 -                               throw new InternalErrorException ();
2459 -                       }
2460 -               }
2461 -
2462                 protected class MoveNextStatement : Statement {
2463                         Iterator iterator;
2464  
2465 @@ -1062,147 +873,17 @@
2466  
2467                         public override bool Resolve (EmitContext ec)
2468                         {
2469 -                               return true;
2470 +                               return iterator.OriginalBlock.Resolve (ec);
2471                         }
2472  
2473                         protected override void DoEmit (EmitContext ec)
2474                         {
2475 -                               iterator.move_next_method.ComputeHost ();
2476 -                               ec.CurrentAnonymousMethod = iterator.move_next_method;
2477 -                               ec.InIterator = true;
2478 -
2479 -                               iterator.EmitMoveNext (ec);
2480 +                               iterator.EmitMoveNext (ec, iterator.Block);
2481                         }
2482                 }
2483  
2484 -               protected class DisposeMethod : Statement {
2485 -                       Iterator iterator;
2486 -
2487 -                       public DisposeMethod (Iterator iterator, Location loc)
2488 -                       {
2489 -                               this.loc = loc;
2490 -                               this.iterator = iterator;
2491 -                       }
2492 -
2493 -                       public override bool Resolve (EmitContext ec)
2494 -                       {
2495 -                               return true;
2496 -                       }
2497 -
2498 -                       protected override void DoEmit (EmitContext ec)
2499 -                       {
2500 -                               iterator.EmitDispose (ec);
2501 -                       }
2502 -               }
2503 -
2504 -               protected class StatementList : Statement {
2505 -                       ArrayList statements;
2506 -
2507 -                       public StatementList (Location loc)
2508 -                       {
2509 -                               this.loc = loc;
2510 -                               statements = new ArrayList ();
2511 -                       }
2512 -
2513 -                       public void Add (Statement statement)
2514 -                       {
2515 -                               statements.Add (statement);
2516 -                       }
2517 -
2518 -                       public override bool Resolve (EmitContext ec)
2519 -                       {
2520 -                               foreach (Statement stmt in statements) {
2521 -                                       if (!stmt.Resolve (ec))
2522 -                                               return false;
2523 -                               }
2524 -
2525 -                               return true;
2526 -                       }
2527 -
2528 -                       protected override void DoEmit (EmitContext ec)
2529 -                       {
2530 -                               foreach (Statement stmt in statements)
2531 -                                       stmt.Emit (ec);
2532 -                       }
2533 -               }
2534 -
2535 -               protected class SetState : Statement
2536 -               {
2537 -                       Iterator iterator;
2538 -                       State state;
2539 -
2540 -                       public SetState (Iterator iterator, State state, Location loc)
2541 -                       {
2542 -                               this.iterator = iterator;
2543 -                               this.state = state;
2544 -                               this.loc = loc;
2545 -                       }
2546 -
2547 -                       public override bool Resolve (EmitContext ec)
2548 -                       {
2549 -                               return true;
2550 -                       }
2551 -
2552 -                       protected override void DoEmit (EmitContext ec)
2553 -                       {
2554 -                               ec.ig.Emit (OpCodes.Ldarg_0);
2555 -                               IntConstant.EmitInt (ec.ig, (int) state);
2556 -                               ec.ig.Emit (OpCodes.Stfld, iterator.pc_field.FieldBuilder);
2557 -                       }
2558 -               }
2559 -
2560 -               protected class InitScope : Statement
2561 -               {
2562 -                       Iterator iterator;
2563 -
2564 -                       public InitScope (Iterator iterator, Location loc)
2565 -                       {
2566 -                               this.iterator = iterator;
2567 -                               this.loc = loc;
2568 -                       }
2569 -
2570 -                       public override bool Resolve (EmitContext ec)
2571 -                       {
2572 -                               return true;
2573 -                       }
2574 -
2575 -                       protected override void DoEmit (EmitContext ec)
2576 -                       {
2577 -                               iterator.cc.EmitInitScope (ec);
2578 -                       }
2579 -               }
2580 -
2581 -               void Define_Reset ()
2582 -               {
2583 -                       Method reset = new Method (
2584 -                               this, null, TypeManager.system_void_expr, Modifiers.PUBLIC,
2585 -                               false, new MemberName ("Reset", Location),
2586 -                               Parameters.EmptyReadOnlyParameters, null);
2587 -                       AddMethod (reset);
2588 -
2589 -                       reset.Block = new ToplevelBlock (Location);
2590 -                       reset.Block = new ToplevelBlock (block, parameters, Location);
2591 -                       reset.Block.SetHaveAnonymousMethods (Location, move_next_method);
2592 -
2593 -                       reset.Block.AddStatement (Create_ThrowNotSupported ());
2594 -               }
2595 -
2596 -               void Define_Dispose ()
2597 -               {
2598 -                       dispose = new Method (
2599 -                               this, null, TypeManager.system_void_expr, Modifiers.PUBLIC,
2600 -                               false, new MemberName ("Dispose", Location),
2601 -                               Parameters.EmptyReadOnlyParameters, null);
2602 -                       AddMethod (dispose);
2603 -
2604 -                       dispose.Block = new ToplevelBlock (block, parameters, Location);
2605 -                       dispose.Block.SetHaveAnonymousMethods (Location, move_next_method);
2606 -
2607 -                       dispose.Block.AddStatement (new DisposeMethod (this, Location));
2608 -               }
2609 -
2610                 public Type IteratorType {
2611 -                       get { return iterator_type_expr.Type; }
2612 +                       get { return IteratorHost.IteratorType; }
2613                 }
2614  
2615                 //
2616 @@ -1212,10 +893,10 @@
2617                 class NoCheckReturn : Statement {
2618                         public Expression Expr;
2619                 
2620 -                       public NoCheckReturn (Expression expr, Location l)
2621 +                       public NoCheckReturn (Expression expr)
2622                         {
2623                                 Expr = expr;
2624 -                               loc = l;
2625 +                               loc = expr.Location;
2626                         }
2627  
2628                         public override bool Resolve (EmitContext ec)
2629 @@ -1236,10 +917,49 @@
2630                         }
2631                 }
2632  
2633 -               bool CheckType ()
2634 +               public static Iterator CreateIterator (IMethodData method, TypeContainer parent,
2635 +                                                      GenericMethod generic, int modifiers)
2636                 {
2637 -                       Type ret = orig_method.ReturnType;
2638 +                       bool is_enumerable;
2639 +                       Type iterator_type;
2640  
2641 +                       if (!CheckType (method.ReturnType, out iterator_type, out is_enumerable)) {
2642 +                               Report.Error (1624, method.Location,
2643 +                                             "The body of `{0}' cannot be an iterator block " +
2644 +                                             "because `{1}' is not an iterator interface type",
2645 +                                             method.GetSignatureForError (),
2646 +                                             TypeManager.CSharpName (method.ReturnType));
2647 +                               return null;
2648 +                       }
2649 +
2650 +                       Report.Debug (64, "CREATE ITERATOR", parent, method, method.Block);
2651 +
2652 +                       ToplevelBlock block = new ToplevelBlock (method.ParameterInfo, method.Location);
2653 +
2654 +                       Iterator iterator = new Iterator (
2655 +                               method, parent, generic, null, block, modifiers,
2656 +                               iterator_type, is_enumerable);
2657 +
2658 +#if FIXME
2659 +                       if (!iterator.RootScope.Define ())
2660 +                               return null;
2661 +                       if (iterator.RootScope.DefineType () == null)
2662 +                               return null;
2663 +                       if (!iterator.RootScope.ResolveType ())
2664 +                               return null;
2665 +#endif
2666 +
2667 +                       Report.Debug (64, "CREATE ITERATOR #1", iterator, iterator.RootScope,
2668 +                                     iterator.RootScope.IsGeneric, iterator.RootScope.TypeBuilder);
2669 +
2670 +                       return iterator;
2671 +               }
2672 +
2673 +               static bool CheckType (Type ret, out Type original_iterator_type, out bool is_enumerable)
2674 +               {
2675 +                       original_iterator_type = null;
2676 +                       is_enumerable = false;
2677 +
2678                         if (ret == TypeManager.ienumerable_type) {
2679                                 original_iterator_type = TypeManager.object_type;
2680                                 is_enumerable = true;
2681 Index: cs-parser.jay
2682 ===================================================================
2683 --- cs-parser.jay       (revision 63019)
2684 +++ cs-parser.jay       (working copy)
2685 @@ -35,7 +35,7 @@
2686                 TypeContainer   current_container;
2687                 TypeContainer   current_class;
2688         
2689 -               IIteratorContainer iterator_container;
2690 +               IAnonymousHost anonymous_host;
2691  
2692                 /// <summary>
2693                 ///   Current block is used to add statements as we find
2694 @@ -45,6 +45,9 @@
2695  
2696                 Delegate   current_delegate;
2697  
2698 +               GenericMethod current_generic_method;
2699 +               AnonymousMethodExpression current_anonymous_method;
2700 +
2701                 /// <summary>
2702                 ///   This is used by the unary_expression code to resolve
2703                 ///   a name against a parameter.  
2704 @@ -1064,7 +1067,7 @@
2705  
2706  method_declaration
2707         : method_header {
2708 -               iterator_container = (IIteratorContainer) $1;
2709 +               anonymous_host = (IAnonymousHost) $1;
2710                 if (RootContext.Documentation != null)
2711                         Lexer.doc_state = XmlCommentState.NotAllowed;
2712           }
2713 @@ -1074,8 +1077,9 @@
2714                 method.Block = (ToplevelBlock) $3;
2715                 current_container.AddMethod (method);
2716  
2717 +               anonymous_host = null;
2718 +               current_generic_method = null;
2719                 current_local_parameters = null;
2720 -               iterator_container = null;
2721  
2722                 if (RootContext.Documentation != null)
2723                         Lexer.doc_state = XmlCommentState.Allowed;
2724 @@ -1132,7 +1136,9 @@
2725                 method = new Method (current_class, generic, (Expression) $3, (int) $2, false,
2726                                      name, (Parameters) $6, (Attributes) $1);
2727  
2728 +               anonymous_host = method;
2729                 current_local_parameters = (Parameters) $6;
2730 +               current_generic_method = generic;
2731  
2732                 if (RootContext.Documentation != null)
2733                         method.DocComment = Lexer.consume_doc_comment ();
2734 @@ -1168,7 +1174,9 @@
2735                 method = new Method (current_class, generic, TypeManager.system_void_expr,
2736                                      (int) $2, false, name, (Parameters) $6, (Attributes) $1);
2737  
2738 +               anonymous_host = method;
2739                 current_local_parameters = (Parameters) $6;
2740 +               current_generic_method = generic;
2741  
2742                 if (RootContext.Documentation != null)
2743                         method.DocComment = Lexer.consume_doc_comment ();
2744 @@ -1444,7 +1452,7 @@
2745                         current_local_parameters = indexer_parameters;
2746                 lexer.PropertyParsing = false;
2747  
2748 -               iterator_container = SimpleIteratorContainer.GetSimple ();
2749 +               anonymous_host = SimpleAnonymousHost.GetSimple ();
2750           }
2751            accessor_body
2752           {
2753 @@ -1457,11 +1465,9 @@
2754                 current_local_parameters = null;
2755                 lexer.PropertyParsing = true;
2756  
2757 -               if (SimpleIteratorContainer.Simple.Yields)
2758 -                       accessor.SetYields ();
2759 +               SimpleAnonymousHost.Simple.Propagate (accessor);
2760 +               anonymous_host = null;
2761  
2762 -               iterator_container = null;
2763 -
2764                 if (RootContext.Documentation != null)
2765                         if (Lexer.doc_state == XmlCommentState.Error)
2766                                 Lexer.doc_state = XmlCommentState.NotAllowed;
2767 @@ -1499,7 +1505,7 @@
2768                 
2769                 lexer.PropertyParsing = false;
2770  
2771 -               iterator_container = SimpleIteratorContainer.GetSimple ();
2772 +               anonymous_host = SimpleAnonymousHost.GetSimple ();
2773           }
2774           accessor_body
2775           {
2776 @@ -1512,11 +1518,9 @@
2777                 current_local_parameters = null;
2778                 lexer.PropertyParsing = true;
2779  
2780 -               if (SimpleIteratorContainer.Simple.Yields)
2781 -                       accessor.SetYields ();
2782 +               SimpleAnonymousHost.Simple.Propagate (accessor);
2783 +               anonymous_host = null;
2784  
2785 -               iterator_container = null;
2786 -
2787                 if (RootContext.Documentation != null
2788                         && Lexer.doc_state == XmlCommentState.Error)
2789                         Lexer.doc_state = XmlCommentState.NotAllowed;
2790 @@ -1940,7 +1944,7 @@
2791  operator_declaration
2792         : opt_attributes opt_modifiers operator_declarator 
2793           {
2794 -               iterator_container = SimpleIteratorContainer.GetSimple ();
2795 +               anonymous_host = SimpleAnonymousHost.GetSimple ();
2796           }
2797           operator_body
2798           {
2799 @@ -1965,14 +1969,13 @@
2800                         Lexer.doc_state = XmlCommentState.Allowed;
2801                 }
2802  
2803 -               if (SimpleIteratorContainer.Simple.Yields)
2804 -                       op.SetYields ();
2805 +               SimpleAnonymousHost.Simple.Propagate (op);
2806 +               anonymous_host = null;
2807  
2808                 // Note again, checking is done in semantic analysis
2809                 current_container.AddOperator (op);
2810  
2811                 current_local_parameters = null;
2812 -               iterator_container = null;
2813           }
2814         ;
2815  
2816 @@ -2432,7 +2435,7 @@
2817                 parsing_indexer  = true;
2818                 
2819                 indexer_parameters = decl.param_list;
2820 -               iterator_container = SimpleIteratorContainer.GetSimple ();
2821 +               anonymous_host = SimpleAnonymousHost.GetSimple ();
2822           }
2823            accessor_declarations 
2824           {
2825 @@ -3396,6 +3399,7 @@
2826                 if (oob_stack == null)
2827                         oob_stack = new Stack (6);
2828  
2829 +               oob_stack.Push (current_anonymous_method);
2830                 oob_stack.Push (current_local_parameters);
2831                 current_local_parameters = (Parameters)$2;
2832  
2833 @@ -3403,7 +3407,12 @@
2834                 oob_stack.Push (current_block);
2835                 oob_stack.Push (top_current_block);
2836                 current_block = null;
2837 -         } 
2838 +
2839 +               Location loc = (Location) $1;
2840 +               current_anonymous_method = new AnonymousMethodExpression (
2841 +                       current_anonymous_method, current_generic_method, current_container,
2842 +                       (Parameters) $2, (ToplevelBlock) top_current_block, loc);
2843 +         }
2844           block
2845           {
2846                 Location loc = (Location) $1;
2847 @@ -3416,11 +3425,20 @@
2848                         ToplevelBlock anon_block = (ToplevelBlock) $4;
2849  
2850                         anon_block.Parent = current_block;
2851 -                       $$ = new AnonymousMethod (current_container, (Parameters) $2, (ToplevelBlock) top_current_block, 
2852 -                               anon_block, loc);
2853 +
2854 +                       Report.Debug (64, "PARSER", anon_block, current_anonymous_method, anonymous_host,
2855 +                                     loc);
2856 +
2857 +                       current_anonymous_method.Block = anon_block;
2858 +                       if ((anonymous_host != null) && (current_anonymous_method.Parent == null))
2859 +                               anonymous_host.AddAnonymousMethod (current_anonymous_method);
2860 +
2861 +                       $$ = current_anonymous_method;
2862                 }
2863 -                       current_local_parameters = (Parameters) oob_stack.Pop ();
2864 -               }
2865 +
2866 +               current_local_parameters = (Parameters) oob_stack.Pop ();
2867 +               current_anonymous_method = (AnonymousMethodExpression) oob_stack.Pop ();
2868 +       }
2869         ;
2870  
2871  opt_anonymous_method_signature
2872 @@ -4000,7 +4018,8 @@
2873         : OPEN_BRACE 
2874           {
2875                 if (current_block == null){
2876 -                       current_block = new ToplevelBlock ((ToplevelBlock) top_current_block, current_local_parameters, (Location) $1);
2877 +                       current_block = new ToplevelBlock ((ToplevelBlock) top_current_block, current_local_parameters,
2878 +                                                          current_generic_method, (Location) $1);
2879                         top_current_block = current_block;
2880                 } else {
2881                         current_block = new Block (current_block, (Location) $1, Location.Null);
2882 @@ -4616,11 +4635,11 @@
2883                         Report.FeatureIsNotStandardized (lt.Location, "yield statement");
2884                         $$ = null;
2885                 }
2886 -               if (iterator_container == null){
2887 +               if (anonymous_host == null){
2888                         Report.Error (204, lt.Location, "yield statement can only be used within a method, operator or property");
2889                         $$ = null;
2890                 } else {
2891 -                       iterator_container.SetYields ();
2892 +                       anonymous_host.SetYields ();
2893                         $$ = new Yield ((Expression) $3, lt.Location); 
2894                 }
2895           }
2896 @@ -4641,11 +4660,11 @@
2897                         Report.FeatureIsNotStandardized (lt.Location, "yield statement");
2898                         $$ = null;
2899                 }
2900 -               if (iterator_container == null){
2901 +               if (anonymous_host == null){
2902                         Report.Error (204, lt.Location, "yield statement can only be used within a method, operator or property");
2903                         $$ = null;
2904                 } else {
2905 -                       iterator_container.SetYields ();
2906 +                       anonymous_host.SetYields ();
2907                         $$ = new YieldBreak (lt.Location);
2908                 }
2909           }
2910 @@ -5006,22 +5025,41 @@
2911  }
2912  
2913  //
2914 -// We use this when we do not have an object in advance that is an IIteratorContainer
2915 +// We use this when we do not have an object in advance that is an IAnonymousHost
2916  //
2917 -public class SimpleIteratorContainer : IIteratorContainer {
2918 -       public bool Yields;
2919 +public class SimpleAnonymousHost : IAnonymousHost {
2920 +       public static readonly SimpleAnonymousHost Simple = new SimpleAnonymousHost ();
2921  
2922 -       public static SimpleIteratorContainer Simple = new SimpleIteratorContainer ();
2923 +       bool yields;
2924 +       ArrayList anonymous_methods;
2925  
2926 -       //
2927 -       // Reset and return
2928 -       //
2929 -       public static SimpleIteratorContainer GetSimple () { 
2930 -               Simple.Yields = false;
2931 +       public static SimpleAnonymousHost GetSimple () {
2932 +               Simple.yields = false;
2933 +               Simple.anonymous_methods = null;
2934                 return Simple;
2935         }
2936  
2937 -       public void SetYields () { Yields = true; } 
2938 +       public void SetYields ()
2939 +       {
2940 +               yields = true;
2941 +       }
2942 +
2943 +       public void AddAnonymousMethod (AnonymousMethodExpression anonymous)
2944 +       {
2945 +               if (anonymous_methods == null)
2946 +                       anonymous_methods = new ArrayList ();
2947 +               anonymous_methods.Add (anonymous);
2948 +       }
2949 +
2950 +       public void Propagate (IAnonymousHost real_host)
2951 +       {
2952 +               if (yields)
2953 +                       real_host.SetYields ();
2954 +               if (anonymous_methods != null) {
2955 +                       foreach (AnonymousMethodExpression ame in anonymous_methods)
2956 +                               real_host.AddAnonymousMethod (ame);
2957 +               }
2958 +       }
2959  }
2960  
2961  // <summary>
2962 Index: convert.cs
2963 ===================================================================
2964 --- convert.cs  (revision 63019)
2965 +++ convert.cs  (working copy)
2966 @@ -838,8 +838,8 @@
2967                                 if (!TypeManager.IsDelegateType (target_type))
2968                                         return false;
2969  
2970 -                               AnonymousMethod am = (AnonymousMethod) expr;
2971 -                               return am.ImplicitStandardConversionExists (target_type);
2972 +                               AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
2973 +                               return ame.ImplicitStandardConversionExists (target_type);
2974                         }
2975  
2976                         return false;
2977 @@ -1325,10 +1325,11 @@
2978                                         return null;
2979                                 }
2980  
2981 -                               AnonymousMethod am = (AnonymousMethod) expr;
2982 +                               AnonymousMethodExpression ame = (AnonymousMethodExpression) expr;
2983 +
2984                                 int errors = Report.Errors;
2985  
2986 -                               Expression conv = am.Compatible (ec, target_type);
2987 +                               Expression conv = ame.Compatible (ec, target_type);
2988                                 if (conv != null)
2989                                         return conv;
2990                                 
2991 Index: anonymous.cs
2992 ===================================================================
2993 --- anonymous.cs        (revision 63019)
2994 +++ anonymous.cs        (working copy)
2995 @@ -20,297 +20,742 @@
2996  
2997  namespace Mono.CSharp {
2998  
2999 -       public abstract class AnonymousContainer : Expression
3000 +       public abstract class CompilerGeneratedClass : Class
3001         {
3002 -               // Used to generate unique method names.
3003 -               protected static int anonymous_method_count;
3004 -                   
3005 -               // An array list of AnonymousMethodParameter or null
3006 -               public Parameters Parameters;
3007 -               
3008 -               //
3009 -               // The block that makes up the body for the anonymous mehtod
3010 -               //
3011 -               public ToplevelBlock Block;
3012 +               GenericMethod generic_method;
3013 +               static int next_index = 0;
3014  
3015 -               //
3016 -               // The container block for this anonymous method.
3017 -               //
3018 -               public Block ContainingBlock;
3019 +               private static MemberName MakeProxyName (GenericMethod generic, Location loc)
3020 +               {
3021 +                       string name = String.Format ("<>c__CompilerGenerated{0}", ++next_index);
3022 +                       if (generic != null) {
3023 +                               TypeArguments args = new TypeArguments (loc);
3024 +                               foreach (TypeParameter tparam in generic.CurrentTypeParameters)
3025 +                                       args.Add (new SimpleName (tparam.Name, loc));
3026 +                               return new MemberName (name, args, loc);
3027 +                       } else
3028 +                               return new MemberName (name, loc);
3029 +               }
3030  
3031 -               //
3032 -               // The implicit method we create
3033 -               //
3034 -               public Method method;
3035 +               protected string MakeName (string prefix)
3036 +               {
3037 +                       return String.Format ("<>c__{0}{1}", prefix, ++next_index);
3038 +               }
3039  
3040 -               protected MethodInfo invoke_mb;
3041 -               
3042 -               // The emit context for the anonymous method
3043 -               public EmitContext aec;
3044 -               public string[] TypeParameters;
3045 -               public Type[] TypeArguments;
3046 -               protected bool unreachable;
3047 +               protected CompilerGeneratedClass (TypeContainer parent, GenericMethod generic,
3048 +                                                 int mod, Location loc)
3049 +                       : base (parent.NamespaceEntry, parent,
3050 +                               MakeProxyName (generic, loc), mod, null)
3051 +               {
3052 +                       this.generic_method = generic;
3053  
3054 -               // The method scope
3055 -               ScopeInfo method_scope;
3056 -               bool computed_method_scope = false;
3057 -               
3058 -               //
3059 -               // The modifiers applied to the method, we aggregate them
3060 -               //
3061 -               protected int method_modifiers = Modifiers.PRIVATE;
3062 -               
3063 -               //
3064 -               // Track the scopes that this method has used.  At the
3065 -               // end this is used to determine the ScopeInfo that will
3066 -               // host the method
3067 -               //
3068 -               ArrayList scopes_used = new ArrayList ();
3069 -               
3070 -               //
3071 -               // Points to our container anonymous method if its present
3072 -               //
3073 -               public AnonymousContainer ContainerAnonymousMethod;     
3074 +                       if (generic != null) {
3075 +                               ArrayList list = new ArrayList ();
3076 +                               foreach (TypeParameter tparam in generic.TypeParameters) {
3077 +                                       if (tparam.Constraints != null)
3078 +                                               list.Add (tparam.Constraints.Clone ());
3079 +                               }
3080 +                               SetParameterInfo (list);
3081 +                       }
3082  
3083 -               protected AnonymousContainer (Parameters parameters, ToplevelBlock container,
3084 -                                             ToplevelBlock block, Location l)
3085 +                       parent.AddCompilerGeneratedClass (this);
3086 +               }
3087 +
3088 +               protected override bool DefineNestedTypes ()
3089                 {
3090 -                       Parameters = parameters;
3091 -                       Block = block;
3092 -                       loc = l;
3093 +                       RootContext.RegisterCompilerGeneratedType (TypeBuilder);
3094 +                       return base.DefineNestedTypes ();
3095 +               }
3096  
3097 -                       //
3098 -                       // The order is important: this setups the CaptureContext tree hierarchy.
3099 -                       //
3100 -                       if (container == null) {
3101 -                               return;
3102 +               protected override bool DoDefineMembers ()
3103 +               {
3104 +                       if (!PopulateType ())
3105 +                               throw new InternalErrorException ();
3106 +
3107 +                       members_defined = true;
3108 +
3109 +                       if (!base.DoDefineMembers ())
3110 +                               return false;
3111 +
3112 +                       if (CompilerGenerated != null) {
3113 +                               foreach (CompilerGeneratedClass c in CompilerGenerated) {
3114 +                                       if (!c.DefineMembers ())
3115 +                                               throw new InternalErrorException ();
3116 +                               }
3117                         }
3118 -                       container.SetHaveAnonymousMethods (l, this);
3119 -                       block.SetHaveAnonymousMethods (l, this);
3120 +
3121 +                       return true;
3122                 }
3123  
3124 -               protected AnonymousContainer (Parameters parameters, ToplevelBlock container,
3125 -                                             Location l):
3126 -                       this (parameters, container, new ToplevelBlock (container, parameters, l), l)
3127 +               protected override bool DoPopulateType ()
3128                 {
3129 +                       if (CompilerGenerated != null) {
3130 +                               foreach (CompilerGeneratedClass c in CompilerGenerated) {
3131 +                                       if (!c.PopulateType ())
3132 +                                               return false;
3133 +                               }
3134 +                       }
3135 +
3136 +                       return true;
3137                 }
3138  
3139 -               public override Expression DoResolve (EmitContext ec)
3140 +               public GenericMethod GenericMethod {
3141 +                       get { return generic_method; }
3142 +               }
3143 +
3144 +               protected TypeExpr InflateType (Type it)
3145                 {
3146 -                       //
3147 -                       // Set class type, set type
3148 -                       //
3149 +                       if (generic_method == null)
3150 +                               return new TypeExpression (it, Location);
3151  
3152 -                       eclass = ExprClass.Value;
3153 +                       if (it.IsGenericParameter && (it.DeclaringMethod != null)) {
3154 +                               int pos = it.GenericParameterPosition;
3155 +                               it = CurrentTypeParameters [pos].Type;
3156 +                       } else if (it.IsGenericType) {
3157 +                               Type[] args = it.GetGenericArguments ();
3158  
3159 -                       //
3160 -                       // This hack means `The type is not accessible
3161 -                       // anywhere', we depend on special conversion
3162 -                       // rules.
3163 -                       // 
3164 -                       type = TypeManager.anonymous_method_type;
3165 +                               TypeArguments inflated = new TypeArguments (Location);
3166 +                               foreach (Type t in args)
3167 +                                       inflated.Add (InflateType (t));
3168  
3169 -                       return this;
3170 +                               return new ConstructedType (it, inflated, Location);
3171 +                       } else if (it.IsArray) {
3172 +                               TypeExpr et_expr = InflateType (it.GetElementType ());
3173 +                               int rank = it.GetArrayRank ();
3174 +
3175 +                               Type et = et_expr.ResolveAsTypeTerminal (this, false).Type;
3176 +                               it = et.MakeArrayType (rank);
3177 +                       }
3178 +
3179 +                       return new TypeExpression (it, Location);
3180                 }
3181  
3182 -               public void RegisterScope (ScopeInfo scope)
3183 +               public Field CaptureVariable (string name, Type type)
3184                 {
3185 -                       if (scopes_used.Contains (scope))
3186 -                               return;
3187 -                       scopes_used.Add (scope);
3188 +                       if (members_defined)
3189 +                               throw new InternalErrorException ("Helper class already defined!");
3190 +                       if (type == null)
3191 +                               throw new ArgumentNullException ();
3192 +
3193 +                       return new CapturedVariable (this, name, InflateType (type));
3194                 }
3195  
3196 -               // Returns the deepest of two scopes
3197 -               ScopeInfo Deepest (ScopeInfo a, ScopeInfo b)
3198 +               bool members_defined;
3199 +
3200 +               internal void CheckMembersDefined ()
3201                 {
3202 -                       ScopeInfo p;
3203 +                       if (members_defined)
3204 +                               throw new InternalErrorException ("Helper class already defined!");
3205 +               }
3206  
3207 -                       if (a == null)
3208 -                               return b;
3209 -                       if (b == null)
3210 -                               return a;
3211 -                       if (a == b)
3212 -                               return a;
3213 +               public override void EmitType ()
3214 +               {
3215 +                       Report.Debug (64, "COMPILER GENERATED EMIT TYPE", this, CompilerGenerated);
3216 +                       base.EmitType ();
3217 +               }
3218  
3219 -                       //
3220 -                       // If they Scopes are on the same CaptureContext, we do the double
3221 -                       // checks just so if there is an invariant change in the future,
3222 -                       // we get the exception at the end
3223 -                       //
3224 -                       for (p = a; p != null; p = p.ParentScope)
3225 -                               if (p == b)
3226 -                                       return a;
3227 -                       
3228 -                       for (p = b; p != null; p = p.ParentScope)
3229 -                               if (p == a)
3230 -                                       return b;
3231 +               protected class CapturedVariable : Field
3232 +               {
3233 +                       public CapturedVariable (CompilerGeneratedClass helper, string name,
3234 +                                                TypeExpr type)
3235 +                               : base (helper, type, Modifiers.INTERNAL, name, null, helper.Location)
3236 +                       {
3237 +                               helper.AddField (this);
3238 +                       }
3239 +               }
3240 +       }
3241  
3242 -                       CaptureContext ca = a.CaptureContext;
3243 -                       CaptureContext cb = b.CaptureContext;
3244 +       public abstract class ScopeInfoBase : CompilerGeneratedClass
3245 +       {
3246 +               public Block ScopeBlock;
3247  
3248 -                       for (CaptureContext c = ca; c != null; c = c.ParentCaptureContext)
3249 -                               if (c == cb)
3250 -                                       return a;
3251 +               protected ScopeInfoBase (TypeContainer parent, GenericMethod generic,
3252 +                                        int mod, Location loc)
3253 +                       : base (parent, generic, mod, loc)
3254 +               { }
3255  
3256 -                       for (CaptureContext c = cb; c != null; c = c.ParentCaptureContext)
3257 -                               if (c == ca)
3258 -                                       return b;
3259 -                       throw new Exception ("Should never be reached");
3260 +               TypeExpr scope_type;
3261 +               protected Field scope_instance;
3262 +               protected ScopeInitializerBase scope_initializer;
3263 +
3264 +               public abstract AnonymousMethodHost Host {
3265 +                       get;
3266                 }
3267  
3268 -               //
3269 -               // Determines the proper host for a method considering the
3270 -               // scopes it references
3271 -               //
3272 -               public void ComputeMethodHost ()
3273 +               public Field ScopeInstance {
3274 +                       get { return scope_instance; }
3275 +               }
3276 +
3277 +               public Type ScopeType {
3278 +                       get { return scope_type.Type; }
3279 +               }
3280 +
3281 +               public void EmitScopeInstance (EmitContext ec)
3282                 {
3283 -                       if (computed_method_scope)
3284 -                               return;
3285 -                       
3286 -                       method_scope = null;
3287 -                       int top = scopes_used.Count;
3288 -                       computed_method_scope = true;
3289 +                       if (scope_initializer == null) {
3290 +                               //
3291 +                               // This is needed if someone overwrites the Emit method
3292 +                               // of Statement and manually calls Block.Emit without
3293 +                               // this snippet first:
3294 +                               // 
3295 +                               //   ec.EmitScopeInitFromBlock (The_Block);
3296 +                               //   The_Block.Emit (ec);
3297 +                               // 
3298 +                               throw new InternalErrorException ();
3299 +                       }
3300  
3301 -                       if (top == 0)
3302 +                       scope_initializer.Emit (ec);
3303 +               }
3304 +
3305 +               public ExpressionStatement GetScopeInitializer (EmitContext ec)
3306 +               {
3307 +                       Report.Debug (64, "GET SCOPE INITIALIZER",
3308 +                                     this, GetType (), scope_initializer, ScopeBlock);
3309 +
3310 +                       if (scope_initializer == null) {
3311 +                               scope_initializer = CreateScopeInitializer ();
3312 +                               if (scope_initializer.Resolve (ec) == null)
3313 +                                       throw new InternalErrorException ();
3314 +                       }
3315 +
3316 +                       return scope_initializer;
3317 +               }
3318 +
3319 +               protected abstract ScopeInitializerBase CreateScopeInitializer ();
3320 +
3321 +               protected override bool DoPopulateType ()
3322 +               {
3323 +                       Report.Debug (64, "SCOPE INFO RESOLVE TYPE", this, GetType (), IsGeneric,
3324 +                                     Parent.IsGeneric, GenericMethod);
3325 +
3326 +                       if (IsGeneric) {
3327 +                               TypeArguments targs = new TypeArguments (Location);
3328 +                               if (Parent.IsGeneric)
3329 +                                       foreach (TypeParameter t in Parent.TypeParameters)
3330 +                                               targs.Add (new TypeParameterExpr (t, Location));
3331 +                               if (GenericMethod != null)
3332 +                                       foreach (TypeParameter t in GenericMethod.TypeParameters)
3333 +                                               targs.Add (new TypeParameterExpr (t, Location));
3334 +
3335 +                               scope_type = new ConstructedType (TypeBuilder, targs, Location);
3336 +                               scope_type = scope_type.ResolveAsTypeTerminal (this, false);
3337 +                               if ((scope_type == null) || (scope_type.Type == null))
3338 +                                       return false;
3339 +                       } else {
3340 +                               scope_type = new TypeExpression (TypeBuilder, Location);
3341 +                       }
3342 +
3343 +                       if (Host != this)
3344 +                               scope_instance = Host.CaptureScope (this);
3345 +
3346 +                       return base.DoPopulateType ();
3347 +               }
3348 +
3349 +               protected abstract class ScopeInitializerBase : ExpressionStatement
3350 +               {
3351 +                       ScopeInfoBase scope;
3352 +                       LocalBuilder scope_instance;
3353 +                       ConstructorInfo scope_ctor;
3354 +
3355 +                       bool initialized;
3356 +
3357 +                       protected ScopeInitializerBase (ScopeInfoBase scope)
3358 +                       {
3359 +                               this.scope = scope;
3360 +                               this.loc = scope.Location;
3361 +                               eclass = ExprClass.Value;
3362 +                       }
3363 +
3364 +                       public ScopeInfoBase Scope {
3365 +                               get { return scope; }
3366 +                       }
3367 +
3368 +                       public override Expression DoResolve (EmitContext ec)
3369 +                       {
3370 +                               if (scope_ctor != null)
3371 +                                       return this;
3372 +
3373 +                               Report.Debug (64, "RESOLVE SCOPE INITIALIZER BASE", this, Scope,
3374 +                                             ec, ec.CurrentBlock);
3375 +
3376 +                               type = Scope.ScopeType;
3377 +
3378 +                               if (!DoResolveInternal (ec))
3379 +                                       throw new InternalErrorException ();
3380 +
3381 +                               return this;
3382 +                       }
3383 +
3384 +                       protected virtual bool DoResolveInternal (EmitContext ec)
3385 +                       {
3386 +                               MethodGroupExpr mg = (MethodGroupExpr) Expression.MemberLookupFinal (
3387 +                                       ec, ec.ContainerType, type, ".ctor", MemberTypes.Constructor,
3388 +                                       AllBindingFlags | BindingFlags.DeclaredOnly, loc);
3389 +                               if (mg == null)
3390 +                                       throw new InternalErrorException ();
3391 +
3392 +                               scope_ctor = (ConstructorInfo) mg.Methods [0];
3393 +
3394 +                               if (Scope.ScopeInstance == null)
3395 +                                       scope_instance = ec.ig.DeclareLocal (type);
3396 +
3397 +                               return true;
3398 +                       }
3399 +
3400 +                       static int next_id;
3401 +                       int id = ++next_id;
3402 +
3403 +                       protected virtual void DoEmit (EmitContext ec)
3404 +                       {
3405 +                               if (ec.CurrentBlock.Toplevel == Scope.ScopeBlock.Toplevel)
3406 +                                       DoEmitInstance (ec);
3407 +                               else
3408 +                                       ec.ig.Emit (OpCodes.Ldarg_0);
3409 +                       }
3410 +
3411 +                       protected void DoEmitInstance (EmitContext ec)
3412 +                       {
3413 +                               ec.ig.Emit (OpCodes.Ldloc, scope_instance);
3414 +                       }
3415 +
3416 +                       protected virtual void EmitScopeConstructor (EmitContext ec)
3417 +                       {
3418 +                               ec.ig.Emit (OpCodes.Newobj, scope_ctor);
3419 +                       }
3420 +
3421 +                       public override void Emit (EmitContext ec)
3422 +                       {
3423 +                               if (!initialized)
3424 +                                       throw new InternalErrorException (
3425 +                                               "Scope {0} not initialized yet", scope);
3426 +
3427 +                               DoEmit (ec);
3428 +                       }
3429 +
3430 +                       public override void EmitStatement (EmitContext ec)
3431 +                       {
3432 +                               if (initialized)
3433 +                                       return;
3434 +
3435 +                               DoEmitStatement (ec);
3436 +                               initialized = true;
3437 +                       }
3438 +
3439 +                       protected virtual void DoEmitStatement (EmitContext ec)
3440 +                       {
3441 +                               Report.Debug (64, "EMIT SCOPE INIT", this, id,
3442 +                                             Scope, scope_instance, ec);
3443 +
3444 +                               ec.ig.Emit (OpCodes.Nop);
3445 +                               ec.ig.Emit (OpCodes.Ldc_I4, id);
3446 +                               ec.ig.Emit (OpCodes.Pop);
3447 +                               ec.ig.Emit (OpCodes.Nop);
3448 +
3449 +                               if (Scope != Scope.Host)
3450 +                                       Scope.Host.EmitScopeInstance (ec);
3451 +                               else if (Scope.ScopeInstance != null)
3452 +                                       ec.ig.Emit (OpCodes.Ldarg_0);
3453 +                               EmitScopeConstructor (ec);
3454 +                               if (Scope.ScopeInstance != null)
3455 +                                       ec.ig.Emit (OpCodes.Stfld, Scope.ScopeInstance.FieldBuilder);
3456 +                               else
3457 +                                       ec.ig.Emit (OpCodes.Stloc, scope_instance);
3458 +                       }
3459 +               }
3460 +       }
3461 +
3462 +       public class AnonymousMethodHost : ScopeInfo
3463 +       {
3464 +               public AnonymousMethodHost (ToplevelBlock toplevel, TypeContainer parent,
3465 +                                           GenericMethod generic, Location loc)
3466 +                       : base (toplevel, parent, generic, loc)
3467 +               {
3468 +                       scopes = new ArrayList ();
3469 +               }
3470 +
3471 +               ArrayList scopes;
3472 +               TypeExpr parent_type;
3473 +               CapturedVariable parent_link;
3474 +               CapturedVariable this_field;
3475 +               Hashtable captured_params;
3476 +
3477 +               public override AnonymousMethodHost Host {
3478 +                       get { return this; }
3479 +               }
3480 +
3481 +               public AnonymousMethodHost ParentHost {
3482 +                       get { return Parent as AnonymousMethodHost; }
3483 +               }
3484 +
3485 +               public Type ParentType {
3486 +                       get { return parent_type.Type; }
3487 +               }
3488 +
3489 +               public Field ParentLink {
3490 +                       get { return parent_link; }
3491 +               }
3492 +
3493 +               public Field THIS {
3494 +                       get { return this_field; }
3495 +               }
3496 +
3497 +               public bool HostsParameters {
3498 +                       get { return captured_params != null; }
3499 +               }
3500 +
3501 +               public Field CaptureThis ()
3502 +               {
3503 +                       if (ParentHost != null)
3504 +                               return ParentHost.CaptureThis ();
3505 +
3506 +                       CheckMembersDefined ();
3507 +                       if (this_field == null)
3508 +                               this_field = new CapturedVariable (this, "<>THIS", parent_type);
3509 +                       return this_field;
3510 +               }
3511 +
3512 +               public Field CaptureScope (ScopeInfoBase scope)
3513 +               {
3514 +                       return CaptureVariable (MakeName ("scope"), scope.ScopeType);
3515 +               }
3516 +
3517 +               public Variable GetCapturedParameter (Parameter par)
3518 +               {
3519 +                       if (captured_params != null)
3520 +                               return (Variable) captured_params [par];
3521 +                       else
3522 +                               return null;
3523 +               }
3524 +
3525 +               public bool IsParameterCaptured (string name)
3526 +               {                       
3527 +                       if (captured_params != null)
3528 +                               return captured_params [name] != null;
3529 +                       return false;
3530 +               }
3531 +
3532 +               public Variable AddParameter (Parameter par, int idx)
3533 +               {
3534 +                       if (captured_params == null)
3535 +                               captured_params = new Hashtable ();
3536 +
3537 +                       Variable var = (Variable) captured_params [par];
3538 +                       if (var == null) {
3539 +                               var = new CapturedParameter (this, par, idx);
3540 +                               captured_params.Add (par, var);
3541 +                               par.IsCaptured = true;
3542 +                       }
3543 +
3544 +                       return var;
3545 +               }
3546 +
3547 +               public void AddScope (ScopeInfo scope)
3548 +               {
3549 +                       scopes.Add (scope);
3550 +               }
3551 +
3552 +               bool linked;
3553 +               public void LinkScopes ()
3554 +               {
3555 +                       if (linked)
3556                                 return;
3557 -                       
3558 -                       method_scope = (ScopeInfo) scopes_used [0];
3559 -                       if (top == 1)
3560 -                               return;
3561 -                       
3562 -                       for (int i = 1; i < top; i++)
3563 -                               method_scope = Deepest (method_scope, (ScopeInfo) scopes_used [i]);
3564 +
3565 +                       linked = true;
3566 +                       if (ParentHost != null)
3567 +                               ParentHost.LinkScopes ();
3568 +
3569 +                       foreach (ScopeInfo si in scopes) {
3570 +                               if (!si.Define ())
3571 +                                       throw new InternalErrorException ();
3572 +                               if (si.DefineType () == null)
3573 +                                       throw new InternalErrorException ();
3574 +                       }
3575                 }
3576  
3577 -               public ScopeInfo Scope {
3578 -                       get {
3579 -                               if (computed_method_scope)
3580 -                                       return method_scope;
3581 +               protected override ScopeInitializerBase CreateScopeInitializer ()
3582 +               {
3583 +                       return new AnonymousMethodHostInitializer (this);
3584 +               }
3585  
3586 +               protected override bool DefineNestedTypes ()
3587 +               {
3588 +                       Report.Debug (64, "ANONYMOUS METHOD HOST NESTED",
3589 +                                     this, Name, Parent, Parent.Name, Parent.IsGeneric);
3590 +
3591 +                       if (Parent.IsGeneric) {
3592 +                               parent_type = new ConstructedType (
3593 +                                       Parent.TypeBuilder, Parent.TypeParameters, Location);
3594 +                               parent_type = parent_type.ResolveAsTypeTerminal (this, false);
3595 +                               if ((parent_type == null) || (parent_type.Type == null))
3596 +                                       return false;
3597 +                       } else {
3598 +                               parent_type = new TypeExpression (Parent.TypeBuilder, Location);
3599 +                       }
3600 +
3601 +                       CompilerGeneratedClass parent = Parent as CompilerGeneratedClass;
3602 +                       if (parent != null)
3603 +                               parent_link = new CapturedVariable (this, "<>parent", parent_type);
3604 +
3605 +                       return base.DefineNestedTypes ();
3606 +               }
3607 +
3608 +               protected override bool DoDefineMembers ()
3609 +               {
3610 +                       Report.Debug (64, "ANONYMOUS METHOD HOST DEFINE MEMBERS",
3611 +                                     this, Name, Parent, CompilerGenerated);
3612 +
3613 +                       ArrayList args = new ArrayList ();
3614 +                       if (this is IteratorHost)
3615 +                               args.Add (new Parameter (
3616 +                                       TypeManager.int32_type, "$PC", Parameter.Modifier.NONE,
3617 +                                       null, Location));
3618 +
3619 +                       Field pfield = Parent is CompilerGeneratedClass ? parent_link : this_field;
3620 +                       if (pfield != null)
3621 +                               args.Add (new Parameter (
3622 +                                       pfield.MemberType, "parent", Parameter.Modifier.NONE,
3623 +                                       null, Location));
3624 +
3625 +                       if (HostsParameters) {
3626 +                               foreach (CapturedParameter cp in captured_params.Values) {
3627 +                                       args.Add (new Parameter (
3628 +                                                         cp.Field.MemberType, cp.Field.Name,
3629 +                                                         Parameter.Modifier.NONE, null, Location));
3630 +                               }
3631 +                       }
3632 +
3633 +                       Parameter[] ctor_params = new Parameter [args.Count];
3634 +                       args.CopyTo (ctor_params, 0);
3635 +                       Constructor ctor = new Constructor (
3636 +                               this, MemberName.Name, Modifiers.PUBLIC,
3637 +                               new Parameters (ctor_params),
3638 +                               new GeneratedBaseInitializer (Location),
3639 +                               Location);
3640 +                       AddConstructor (ctor);
3641 +
3642 +                       ctor.Block = new ToplevelBlock (null, Location);
3643 +                       ctor.Block.AddStatement (new TheCtor (this));
3644 +
3645 +                       return base.DoDefineMembers ();
3646 +               }
3647 +
3648 +               protected virtual void EmitScopeConstructor (EmitContext ec)
3649 +               {
3650 +                       int pos = (this is IteratorHost) ? 2 : 1;
3651 +                       Field pfield = Parent is CompilerGeneratedClass ? parent_link : this_field;
3652 +                       if (pfield != null) {
3653 +                               ec.ig.Emit (OpCodes.Ldarg_0);
3654 +                               ec.ig.Emit (OpCodes.Ldarg, pos);
3655 +                               ec.ig.Emit (OpCodes.Stfld, pfield.FieldBuilder);
3656 +                               pos++;
3657 +                       }
3658 +
3659 +                       if (HostsParameters) {
3660 +                               foreach (CapturedParameter cp in captured_params.Values) {
3661 +                                       ec.ig.Emit (OpCodes.Ldarg_0);
3662 +                                       ParameterReference.EmitLdArg (ec.ig, pos++);
3663 +                                       ec.ig.Emit (OpCodes.Stfld, cp.Field.FieldBuilder);
3664 +                               }
3665 +                       }
3666 +               }
3667 +
3668 +               protected class TheCtor : Statement
3669 +               {
3670 +                       AnonymousMethodHost host;
3671 +
3672 +                       public TheCtor (AnonymousMethodHost host)
3673 +                       {
3674 +                               this.host = host;
3675 +                       }
3676 +
3677 +                       public override bool Resolve (EmitContext ec)
3678 +                       {
3679 +                               return true;
3680 +                       }
3681 +
3682 +                       protected override void DoEmit (EmitContext ec)
3683 +                       {
3684 +                               host.EmitScopeConstructor (ec);
3685 +                       }
3686 +               }
3687 +
3688 +               protected class AnonymousMethodHostInitializer : ScopeInitializer
3689 +               {
3690 +                       AnonymousMethodHost host;
3691 +
3692 +                       public AnonymousMethodHostInitializer (AnonymousMethodHost host)
3693 +                               : base (host)
3694 +                       {
3695 +                               this.host = host;
3696 +                       }
3697 +
3698 +                       public AnonymousMethodHost Host {
3699 +                               get { return host; }
3700 +                       }
3701 +
3702 +                       protected override bool DoResolveInternal (EmitContext ec)
3703 +                       {
3704 +                               Report.Debug (64, "RESOLVE ANONYMOUS METHOD HOST INITIALIZER",
3705 +                                             this, Host, Host.ScopeType, Host.ParentType, loc);
3706 +
3707                                 //
3708 -                               // This means that ComputeMethodHost is not being called, most
3709 -                               // likely by someone who overwrote the CreateMethodHost method
3710 +                               // Copy the parameter values, if any
3711                                 //
3712 -                               throw new Exception ("Internal error, AnonymousContainer.Scope is being used before its container is computed");
3713 +                               if (Host.HostsParameters) {
3714 +                                       foreach (CapturedParameter cp in Host.captured_params.Values) {
3715 +                                               FieldExpr fe = (FieldExpr) Expression.MemberLookup (
3716 +                                                       ec.ContainerType, type, cp.Field.Name, loc);
3717 +                                               if (fe == null)
3718 +                                                       throw new InternalErrorException ();
3719 +
3720 +                                               fe.InstanceExpression = this;
3721 +                                               cp.FieldInstance = fe;
3722 +                                       }
3723 +                               }
3724 +
3725 +                               return base.DoResolveInternal (ec);
3726                         }
3727 +
3728 +                       protected override void EmitScopeConstructor (EmitContext ec)
3729 +                       {
3730 +                               if ((host.THIS != null) || (host.ParentLink != null))
3731 +                                       ec.ig.Emit (OpCodes.Ldarg_0);
3732 +
3733 +                               if (Host.HostsParameters) {
3734 +                                       foreach (CapturedParameter cp in Host.captured_params.Values) {
3735 +                                               EmitParameterReference (ec, cp);
3736 +                                       }
3737 +                               }
3738 +
3739 +                               base.EmitScopeConstructor (ec);
3740 +                       }
3741                 }
3742 -               
3743 -               
3744 -               protected abstract bool CreateMethodHost (EmitContext ec);
3745  
3746 -               public abstract void CreateScopeType (EmitContext ec, ScopeInfo scope);
3747 +       }
3748  
3749 -               public abstract Iterator Iterator {
3750 +       public interface IAnonymousContainer
3751 +       {
3752 +               ToplevelBlock Container {
3753                         get;
3754                 }
3755  
3756 -               public abstract bool IsIterator {
3757 +               GenericMethod GenericMethod {
3758                         get;
3759                 }
3760 +
3761 +               AnonymousMethodHost RootScope {
3762 +                       get;
3763 +               }
3764 +
3765 +               bool IsIterator {
3766 +                       get;
3767 +               }
3768         }
3769  
3770 -       public class AnonymousMethod : AnonymousContainer
3771 +       public interface IAnonymousHost
3772         {
3773 -               TypeContainer host;
3774 +               //
3775 +               // Invoked if a yield statement is found in the body
3776 +               //
3777 +               void SetYields ();
3778  
3779                 //
3780 -               // The value return by the Compatible call, this ensure that
3781 -               // the code works even if invoked more than once (Resolve called
3782 -               // more than once, due to the way Convert.ImplicitConversion works
3783 +               // Invoked if an anonymous method is found in the body
3784                 //
3785 -               Expression anonymous_delegate;
3786 +               void AddAnonymousMethod (AnonymousMethodExpression anonymous);
3787 +       }
3788  
3789 -               public AnonymousMethod (TypeContainer host, Parameters parameters, ToplevelBlock container,
3790 -                                       ToplevelBlock block, Location l)
3791 -                       : base (parameters, container, block, l)
3792 -               {
3793 -                       this.host = host;
3794 +       public class AnonymousMethodExpression : Expression, IAnonymousContainer, IAnonymousHost
3795 +       {
3796 +               public readonly AnonymousMethodExpression Parent;
3797 +               public readonly TypeContainer Host;
3798 +               public readonly Parameters Parameters;
3799 +
3800 +               public ToplevelBlock Block;
3801 +               protected AnonymousMethod anonymous;
3802 +
3803 +               protected readonly ToplevelBlock container;
3804 +               protected readonly GenericMethod generic;
3805 +
3806 +               public ToplevelBlock Container {
3807 +                       get { return container; }
3808                 }
3809  
3810 -               public override Iterator Iterator {
3811 -                       get { return null; }
3812 +               public GenericMethod GenericMethod {
3813 +                       get { return generic; }
3814                 }
3815  
3816 -               public override bool IsIterator {
3817 -                       get { return false; }
3818 +               public AnonymousMethod AnonymousMethod {
3819 +                       get { return anonymous; }
3820                 }
3821  
3822 -               public override void Emit (EmitContext ec)
3823 -               {
3824 -                       // nothing, as we only exist to not do anything.
3825 +               public AnonymousMethodHost RootScope {
3826 +                       get { return root_scope; }
3827                 }
3828  
3829 -               //
3830 -               // Creates the host for the anonymous method
3831 -               //
3832 -               protected override bool CreateMethodHost (EmitContext ec)
3833 +               public AnonymousMethodExpression (AnonymousMethodExpression parent,
3834 +                                                 GenericMethod generic, TypeContainer host,
3835 +                                                 Parameters parameters, ToplevelBlock container,
3836 +                                                 Location loc)
3837                 {
3838 -                       ComputeMethodHost ();
3839 +                       this.Parent = parent;
3840 +                       this.generic = parent != null ? null : generic;
3841 +                       this.Host = host;
3842 +                       this.Parameters = parameters;
3843 +                       this.container = container;
3844 +                       this.loc = loc;
3845  
3846 -                       //
3847 -                       // Crude hack follows: we replace the TypeBuilder during the
3848 -                       // definition to get the method hosted in the right class
3849 -                       //
3850 -                       TypeBuilder current_type = ec.TypeContainer.TypeBuilder;
3851 -                       TypeBuilder type_host = (Scope == null ) ? current_type : Scope.ScopeTypeBuilder;
3852 +                       Report.Debug (64, "NEW ANONYMOUS METHOD EXPRESSION", this, parent, host,
3853 +                                     container, loc);
3854  
3855 -                       if (current_type == null)
3856 -                               throw new Exception ("The current_type is null");
3857 -                       
3858 -                       if (type_host == null)
3859 -                               throw new Exception (String.Format ("Type host is null, method_host is {0}", Scope == null ? "null" : "Not null"));
3860 +                       if (parent != null)
3861 +                               parent.AddAnonymousMethod (this);
3862 +               }
3863  
3864 -                       if (current_type != type_host)
3865 -                               method_modifiers = Modifiers.INTERNAL;
3866 +               ArrayList children;
3867 +               AnonymousMethodHost root_scope;
3868  
3869 -                       if (current_type == type_host && ec.IsStatic){
3870 -                               method_modifiers |= Modifiers.STATIC;
3871 -                               current_type = null;
3872 -                       } 
3873 +               void IAnonymousHost.SetYields ()
3874 +               {
3875 +                       throw new InvalidOperationException ();
3876 +               }
3877  
3878 -                       string name = "<#AnonymousMethod>" + anonymous_method_count++;
3879 -                       MemberName member_name;
3880 +               public void AddAnonymousMethod (AnonymousMethodExpression anonymous)
3881 +               {
3882 +                       if (children == null)
3883 +                               children = new ArrayList ();
3884 +                       children.Add (anonymous);
3885 +               }
3886  
3887 -                       GenericMethod generic_method = null;
3888 -                       if (TypeParameters != null) {
3889 -                               TypeArguments args = new TypeArguments (loc);
3890 -                               foreach (string t in TypeParameters)
3891 -                                       args.Add (new SimpleName (t, loc));
3892 +               public bool CreateAnonymousHelpers ()
3893 +               {
3894 +                       Report.Debug (64, "ANONYMOUS METHOD EXPRESSION CREATE ROOT SCOPE",
3895 +                                     this, Host, container, loc);
3896  
3897 -                               member_name = new MemberName (name, args, loc);
3898 +                       if (container != null)
3899 +                               root_scope = container.CreateAnonymousMethodHost (Host);
3900  
3901 -                               generic_method = new GenericMethod (
3902 -                                       ec.DeclContainer.NamespaceEntry,
3903 -                                       (TypeContainer) ec.TypeContainer, member_name,
3904 -                                       new TypeExpression (invoke_mb.ReturnType, loc),
3905 -                                       Parameters);
3906 +                       if (children != null) {
3907 +                               foreach (AnonymousMethodExpression child in children) {
3908 +                                       if (!child.CreateAnonymousHelpers ())
3909 +                                               return false;
3910 +                               }
3911 +                       }
3912  
3913 -                               generic_method.SetParameterInfo (null);
3914 -                       } else
3915 -                               member_name = new MemberName (name, loc);
3916 +                       return true;
3917 +               }
3918  
3919 -                       method = new Method (
3920 -                               (TypeContainer) ec.TypeContainer, generic_method,
3921 -                               new TypeExpression (invoke_mb.ReturnType, loc),
3922 -                               method_modifiers, false, member_name, Parameters, null);
3923 -                       method.Block = Block;
3924 -
3925 -                       //
3926 -                       // Swap the TypeBuilder while we define the method, then restore
3927 -                       //
3928 -                       if (current_type != null)
3929 -                               ec.TypeContainer.TypeBuilder = type_host;
3930 -                       bool res = method.Define ();
3931 -                       if (current_type != null)
3932 -                               ec.TypeContainer.TypeBuilder = current_type;
3933 -
3934 -                       return res;
3935 +               public override string ExprClassName {
3936 +                       get {
3937 +                               return "anonymous method";
3938 +                       }
3939                 }
3940  
3941                 void Error_ParameterMismatch (Type t)
3942                 {
3943                         Report.Error (1661, loc, "Anonymous method could not be converted to delegate `" +
3944 -                                     "{0}' since there is a parameter mismatch", TypeManager.CSharpName (t));
3945 +                                     "{0}' since there is a parameter mismatch",
3946 +                                     TypeManager.CSharpName (t));
3947                 }
3948  
3949                 public bool ImplicitStandardConversionExists (Type delegate_type)
3950 @@ -318,8 +763,9 @@
3951                         if (Parameters == null)
3952                                 return true;
3953  
3954 -                       MethodGroupExpr invoke_mg = Delegate.GetInvokeMethod (host.TypeBuilder, delegate_type, loc);
3955 -                       invoke_mb = (MethodInfo) invoke_mg.Methods [0];
3956 +                       MethodGroupExpr invoke_mg = Delegate.GetInvokeMethod (
3957 +                               Host.TypeBuilder, delegate_type, loc);
3958 +                       MethodInfo invoke_mb = (MethodInfo) invoke_mg.Methods [0];
3959                         ParameterData invoke_pd = TypeManager.GetParameterData (invoke_mb);
3960  
3961                         if (Parameters.Count != invoke_pd.Count)
3962 @@ -338,31 +784,20 @@
3963                 //
3964                 public Expression Compatible (EmitContext ec, Type delegate_type)
3965                 {
3966 -                       if (anonymous_delegate != null)
3967 -                               return anonymous_delegate;
3968 -                       
3969 +                       if (anonymous != null)
3970 +                               return anonymous.AnonymousDelegate;
3971 +
3972                         //
3973                         // At this point its the first time we know the return type that is 
3974                         // needed for the anonymous method.  We create the method here.
3975                         //
3976  
3977 -                       MethodGroupExpr invoke_mg = Delegate.GetInvokeMethod (ec.ContainerType, delegate_type, loc);
3978 -                       invoke_mb = (MethodInfo) invoke_mg.Methods [0];
3979 +                       MethodGroupExpr invoke_mg = Delegate.GetInvokeMethod (
3980 +                               ec.ContainerType, delegate_type, loc);
3981 +                       MethodInfo invoke_mb = (MethodInfo) invoke_mg.Methods [0];
3982                         ParameterData invoke_pd = TypeManager.GetParameterData (invoke_mb);
3983  
3984 -                       if (delegate_type.IsGenericType) {
3985 -                               Type def = delegate_type.GetGenericTypeDefinition ();
3986 -
3987 -                               if (def != delegate_type) {
3988 -                                       Type[] tparam = TypeManager.GetTypeArguments (def);
3989 -
3990 -                                       TypeArguments = TypeManager.GetTypeArguments (delegate_type);
3991 -                                       TypeParameters = new string [tparam.Length];
3992 -                                       for (int i = 0; i < tparam.Length; i++)
3993 -                                               TypeParameters [i] = tparam [i].Name;
3994 -                               }
3995 -                       }
3996 -
3997 +                       Parameters parameters;
3998                         if (Parameters == null) {
3999                                 //
4000                                 // We provide a set of inaccessible parameters
4001 @@ -375,7 +810,9 @@
4002                                                 "+" + i, invoke_pd.ParameterModifier (i), null, loc);
4003                                 }
4004                                                                 
4005 -                               Parameters = new Parameters (fixedpars);
4006 +                               parameters = new Parameters (fixedpars);
4007 +                               if (!parameters.Resolve (ec))
4008 +                                       return null;
4009                         } else {
4010                                 if (Parameters.Count != invoke_pd.Count) {
4011                                         Report.SymbolRelatedToPreviousError (delegate_type);
4012 @@ -407,8 +844,10 @@
4013                                                 return null;
4014                                         }
4015                                 }
4016 +
4017 +                               parameters = Parameters;
4018                         }
4019 -                       
4020 +
4021                         //
4022                         // Second: the return type of the delegate must be compatible with 
4023                         // the anonymous type.   Instead of doing a pass to examine the block
4024 @@ -419,135 +858,309 @@
4025                         //MethodBuilder builder = method_data.MethodBuilder;
4026                         //ILGenerator ig = builder.GetILGenerator ();
4027  
4028 -                       aec = new EmitContext (ec.ResolveContext,
4029 -                               ec.TypeContainer, ec.DeclContainer, loc, null,
4030 -                               invoke_mb.ReturnType,
4031 -                               /* REVIEW */ (ec.InIterator ? Modifiers.METHOD_YIELDS : 0) |
4032 -                               (ec.InUnsafe ? Modifiers.UNSAFE : 0) |
4033 -                               (ec.IsStatic ? Modifiers.STATIC : 0),
4034 -                               /* No constructor */ false);
4035 +                       Report.Debug (64, "COMPATIBLE", this, Parent, GenericMethod, Host,
4036 +                                     Container, Block, invoke_mb.ReturnType, delegate_type,
4037 +                                     delegate_type.IsGenericType, loc);
4038  
4039 -                       aec.CurrentAnonymousMethod = this;
4040 -                       ContainerAnonymousMethod = ec.CurrentAnonymousMethod;
4041 -                       ContainingBlock = ec.CurrentBlock;
4042 +                       anonymous = new AnonymousMethod (
4043 +                               Parent != null ? Parent.AnonymousMethod : null, RootScope, Host,
4044 +                               GenericMethod, parameters, Container, Block, invoke_mb.ReturnType,
4045 +                               delegate_type, loc);
4046  
4047 -                       if (aec.ResolveTopBlock (ec, Block, Parameters, null, out unreachable)){
4048 -                               anonymous_delegate = new AnonymousDelegate (
4049 -                                       this, delegate_type, loc).Resolve (ec);
4050 -                               return anonymous_delegate;
4051 -                       }
4052 -                       return null;
4053 +                       if (!anonymous.Resolve (ec))
4054 +                               return null;
4055 +
4056 +                       return anonymous.AnonymousDelegate;
4057                 }
4058  
4059                 public override Expression DoResolve (EmitContext ec)
4060                 {
4061 -                       if (!ec.IsAnonymousMethodAllowed) {
4062 -                               Report.Error (1706, loc, "Anonymous methods are not allowed in the attribute declaration");
4063 -                               return null;
4064 -                       }
4065 +                       //
4066 +                       // Set class type, set type
4067 +                       //
4068  
4069 -                       if (Parameters != null && !Parameters.Resolve (ec)) {
4070 +                       eclass = ExprClass.Value;
4071 +
4072 +                       //
4073 +                       // This hack means `The type is not accessible
4074 +                       // anywhere', we depend on special conversion
4075 +                       // rules.
4076 +                       // 
4077 +                       type = TypeManager.anonymous_method_type;
4078 +
4079 +                       if ((Parameters != null) && !Parameters.Resolve (ec))
4080                                 return null;
4081 -                       }
4082  
4083 -                       return base.DoResolve (ec);
4084 +                       return this;
4085                 }
4086  
4087 +               public override void Emit (EmitContext ec)
4088 +               {
4089 +                       // nothing, as we only exist to not do anything.
4090 +               }
4091  
4092 -               public override string ExprClassName {
4093 -                       get {
4094 -                               return "anonymous method";
4095 -                       }
4096 +               public bool IsIterator {
4097 +                       get { return false; }
4098                 }
4099 +       }
4100  
4101 -               public MethodInfo GetMethodBuilder ()
4102 +       public abstract class AnonymousContainer : IAnonymousContainer
4103 +       {
4104 +               // Used to generate unique method names.
4105 +               protected static int anonymous_method_count;
4106 +
4107 +               public readonly Location Location;
4108 +
4109 +               // An array list of AnonymousMethodParameter or null
4110 +               public readonly Parameters Parameters;
4111 +
4112 +               //
4113 +               // The block that makes up the body for the anonymous mehtod
4114 +               //
4115 +               public readonly ToplevelBlock Block;
4116 +
4117 +               public readonly Type ReturnType;
4118 +               public readonly TypeContainer Host;
4119 +
4120 +               //
4121 +               // The implicit method we create
4122 +               //
4123 +               protected Method method;
4124 +               protected EmitContext aec;
4125 +
4126 +               // The emit context for the anonymous method
4127 +               protected bool unreachable;
4128 +               protected readonly Location loc;
4129 +               protected readonly ToplevelBlock container;
4130 +               protected readonly GenericMethod generic;
4131 +
4132 +               //
4133 +               // Points to our container anonymous method if its present
4134 +               //
4135 +               public readonly AnonymousContainer ContainerAnonymousMethod;
4136 +
4137 +               protected AnonymousContainer (AnonymousContainer parent, TypeContainer host,
4138 +                                             GenericMethod generic, Parameters parameters,
4139 +                                             ToplevelBlock container, ToplevelBlock block,
4140 +                                             Type return_type, int mod, Location loc)
4141                 {
4142 -                       MethodInfo builder = method.MethodBuilder;
4143 -                       if (TypeArguments != null)
4144 -                               return builder.MakeGenericMethod (TypeArguments);
4145 -                       else
4146 -                               return builder;
4147 +                       this.ContainerAnonymousMethod = parent;
4148 +                       this.ReturnType = return_type;
4149 +                       this.Host = host;
4150 +
4151 +                       this.container = container;
4152 +                       this.generic = parent != null ? null : generic;
4153 +                       this.Parameters = parameters;
4154 +                       this.Block = block;
4155 +                       this.loc = loc;
4156                 }
4157  
4158 -               public override string GetSignatureForError ()
4159 +               public Method Method {
4160 +                       get { return method; }
4161 +               }
4162 +
4163 +               public abstract AnonymousMethodHost RootScope {
4164 +                       get;
4165 +               }
4166 +
4167 +               public string GetSignatureForError ()
4168                 {
4169 -                       string s = TypeManager.CSharpSignature (invoke_mb);
4170 -                       return s.Substring (0, s.IndexOf (".Invoke("));
4171 +                       return RootScope.GetSignatureForError ();
4172                 }
4173 -               
4174 -               public bool EmitMethod (EmitContext ec)
4175 +
4176 +               public virtual bool Resolve (EmitContext ec)
4177                 {
4178 -                       if (!CreateMethodHost (ec))
4179 +                       if (!ec.IsAnonymousMethodAllowed) {
4180 +                               Report.Error (1706, loc,
4181 +                                             "Anonymous methods are not allowed in the " +
4182 +                                             "attribute declaration");
4183                                 return false;
4184 +                       }
4185  
4186 -                       MethodBuilder builder = method.MethodBuilder;
4187 -                       ILGenerator ig = builder.GetILGenerator ();
4188 -                       aec.ig = ig;
4189 +                       Report.Debug (64, "RESOLVE ANONYMOUS METHOD", this, loc, ec,
4190 +                                     RootScope, Parameters, ec.IsStatic);
4191  
4192 -                       Parameters.ApplyAttributes (builder);
4193 +                       aec = new EmitContext (
4194 +                               ec.ResolveContext, ec.TypeContainer,
4195 +                               RootScope != null ? RootScope : Host, loc, null, ReturnType,
4196 +                               /* REVIEW */ (ec.InIterator ? Modifiers.METHOD_YIELDS : 0) |
4197 +                               (ec.InUnsafe ? Modifiers.UNSAFE : 0), /* No constructor */ false);
4198  
4199 -                       //
4200 -                       // Adjust based on the computed state of the
4201 -                       // method from CreateMethodHost
4202 -                       
4203 -                       aec.MethodIsStatic = (method_modifiers & Modifiers.STATIC) != 0;
4204 -                       
4205 -                       aec.EmitMeta (Block);
4206 -                       aec.EmitResolvedTopBlock (Block, unreachable);
4207 -                       return true;
4208 +                       aec.CurrentAnonymousMethod = this;
4209 +
4210 +                       Report.Debug (64, "RESOLVE ANONYMOUS METHOD #1", this, loc, ec, aec,
4211 +                                     RootScope, Parameters, Block);
4212 +
4213 +                       bool unreachable;
4214 +                       if (!aec.ResolveTopBlock (ec, Block, Parameters, null, out unreachable))
4215 +                               return false;
4216 +
4217 +                       Report.Debug (64, "RESOLVE ANONYMOUS METHOD #3", this, ec, aec, Block);
4218 +
4219 +                       method = DoCreateMethodHost (ec);
4220 +
4221 +                       if (RootScope == null)
4222 +                               return method.Define ();
4223 +                       else
4224 +                               return true;
4225                 }
4226  
4227 -               public override void CreateScopeType (EmitContext ec, ScopeInfo scope)
4228 -               {
4229 -                       TypeBuilder container = ec.TypeContainer.TypeBuilder;
4230 -                       string name = String.Format ("<>AnonHelp<{0}>", scope.id);
4231 +               protected abstract Method DoCreateMethodHost (EmitContext ec);
4232  
4233 -                       scope.ScopeTypeBuilder = container.DefineNestedType (name,
4234 -                               TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit | TypeAttributes.NestedPrivate,
4235 -                                        TypeManager.object_type);
4236 +               public ToplevelBlock Container {
4237 +                       get { return container; }
4238 +               }
4239  
4240 -                       Type [] constructor_types = Type.EmptyTypes;
4241 -                       ConstructorBuilder ctor = scope.ScopeTypeBuilder.DefineConstructor (
4242 -                               MethodAttributes.Public | MethodAttributes.HideBySig |
4243 -                               MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
4244 -                               CallingConventions.HasThis, constructor_types);
4245 -                       TypeManager.RegisterMethod (ctor, Parameters.EmptyReadOnlyParameters);
4246 +               public GenericMethod GenericMethod {
4247 +                       get { return generic; }
4248 +               }
4249  
4250 -                       ILGenerator cig = ctor.GetILGenerator ();
4251 -                       cig.Emit (OpCodes.Ldarg_0);
4252 -                       cig.Emit (OpCodes.Call, TypeManager.object_ctor);
4253 -                       cig.Emit (OpCodes.Ret);
4254 +               public abstract bool IsIterator {
4255 +                       get;
4256 +               }
4257  
4258 -                       if (ec.TypeContainer.IsGeneric) {
4259 -                               TypeParameter[] tparam = ec.TypeContainer.TypeParameters;
4260 -                               string[] names = new string [tparam.Length];
4261 -                               Type[] types = new Type [tparam.Length];
4262 +#if FIXME
4263 +               public override string ToString ()
4264 +               {
4265 +                       return String.Format ("{0} ({1})", GetType (), Name);
4266 +               }
4267 +#endif
4268  
4269 -                               for (int i = 0; i < names.Length; i++) {
4270 -                                       names [i] = tparam [i].Name;
4271 -                                       types [i] = tparam [i].Type;
4272 +               protected class AnonymousMethodMethod : Method
4273 +               {
4274 +                       public AnonymousContainer AnonymousMethod;
4275 +
4276 +                       public AnonymousMethodMethod (AnonymousContainer am, GenericMethod generic,
4277 +                                                     TypeExpr return_type, int mod, MemberName name,
4278 +                                                     Parameters parameters)
4279 +                               : base (am.RootScope != null ? am.RootScope : am.Host,
4280 +                                       generic, return_type, mod, false, name, parameters, null)
4281 +                       {
4282 +                               this.AnonymousMethod = am;
4283 +
4284 +                               if (am.RootScope != null) {
4285 +                                       am.RootScope.CheckMembersDefined ();
4286 +                                       am.RootScope.AddMethod (this);
4287 +                               } else {
4288 +                                       ModFlags |= Modifiers.STATIC;
4289 +                                       am.Host.AddMethod (this);
4290                                 }
4291 +                               Block = am.Block;
4292 +                       }
4293  
4294 -                               scope.ScopeTypeBuilder.DefineGenericParameters (names);
4295 -                               scope.ScopeTypeBuilder.GetGenericTypeDefinition ();
4296 +                       public override EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
4297 +                       {
4298 +                               EmitContext aec = AnonymousMethod.aec;
4299 +                               aec.ig = ig;
4300 +                               return aec;
4301 +                       }
4302 +               }
4303 +       }
4304  
4305 -                               scope.ScopeType = scope.ScopeTypeBuilder.MakeGenericType (types);
4306 +       public class AnonymousMethod : AnonymousContainer
4307 +       {
4308 +               public readonly Type DelegateType;
4309 +
4310 +               //
4311 +               // The value return by the Compatible call, this ensure that
4312 +               // the code works even if invoked more than once (Resolve called
4313 +               // more than once, due to the way Convert.ImplicitConversion works
4314 +               //
4315 +               Expression anonymous_delegate;
4316 +               AnonymousMethodHost root_scope;
4317 +
4318 +               public AnonymousMethod (AnonymousMethod parent, AnonymousMethodHost root_scope,
4319 +                                       TypeContainer host, GenericMethod generic,
4320 +                                       Parameters parameters, ToplevelBlock container,
4321 +                                       ToplevelBlock block, Type return_type, Type delegate_type,
4322 +                                       Location loc)
4323 +                       : base (parent, host, generic, parameters, container, block,
4324 +                               return_type, 0, loc)
4325 +               {
4326 +                       this.DelegateType = delegate_type;
4327 +                       this.root_scope = root_scope;
4328 +               }
4329 +
4330 +               public override AnonymousMethodHost RootScope {
4331 +                       get { return root_scope; }
4332 +               }
4333 +
4334 +               public override bool IsIterator {
4335 +                       get { return false; }
4336 +               }
4337 +
4338 +               public Expression AnonymousDelegate {
4339 +                       get { return anonymous_delegate; }
4340 +               }
4341 +
4342 +               //
4343 +               // Creates the host for the anonymous method
4344 +               //
4345 +               protected override Method DoCreateMethodHost (EmitContext ec)
4346 +               {
4347 +                       string name = "<>c__AnonymousMethod" + anonymous_method_count++;
4348 +                       MemberName member_name;
4349 +
4350 +                       GenericMethod generic_method = null;
4351 +                       if (DelegateType.IsGenericType) {
4352 +                               TypeArguments args = new TypeArguments (loc);
4353 +
4354 +                               Type[] tparam = TypeManager.GetTypeArguments (DelegateType);
4355 +                               for (int i = 0; i < tparam.Length; i++)
4356 +                                       args.Add (new SimpleName (tparam [i].Name, loc));
4357 +
4358 +                               member_name = new MemberName (name, args, loc);
4359 +
4360 +                               generic_method = new GenericMethod (
4361 +                                       RootScope.NamespaceEntry, RootScope, member_name,
4362 +                                       new TypeExpression (ReturnType, loc), Parameters);
4363 +
4364 +                               generic_method.SetParameterInfo (null);
4365                         } else
4366 -                               scope.ScopeType = scope.ScopeTypeBuilder;
4367 +                               member_name = new MemberName (name, loc);
4368  
4369 +                       return new AnonymousMethodMethod (
4370 +                               this, generic_method, new TypeExpression (ReturnType, loc),
4371 +                               Modifiers.INTERNAL, member_name, Parameters);
4372 +               }
4373  
4374 -                       if (ec.TypeContainer.IsGeneric)
4375 -                               scope.ScopeConstructor = TypeBuilder.GetConstructor (
4376 -                                       scope.ScopeType, ctor);
4377 -                       else
4378 -                               scope.ScopeConstructor = ctor;
4379 +               public override bool Resolve (EmitContext ec)
4380 +               {
4381 +                       if (!base.Resolve (ec))
4382 +                               return false;
4383 +
4384 +                       anonymous_delegate = new AnonymousDelegate (this, DelegateType, loc).Resolve (ec);
4385 +                       if (anonymous_delegate == null)
4386 +                               return false;
4387 +
4388 +                       return true;
4389                 }
4390  
4391 +               public MethodInfo GetMethodBuilder (EmitContext ec)
4392 +               {
4393 +                       MethodInfo builder = method.MethodBuilder;
4394 +                       if ((RootScope != null) && RootScope.IsGeneric) {
4395 +                               MethodGroupExpr mg = (MethodGroupExpr) Expression.MemberLookup (
4396 +                                       ec.ContainerType, RootScope.ScopeType, builder.Name, loc);
4397 +
4398 +                               if (mg == null)
4399 +                                       throw new InternalErrorException ();
4400 +                               builder = (MethodInfo) mg.Methods [0];
4401 +                       }
4402 +
4403 +                       if (!DelegateType.IsGenericType)
4404 +                               return builder;
4405 +
4406 +                       Type[] targs = TypeManager.GetTypeArguments (DelegateType);
4407 +                       return builder.MakeGenericMethod (targs);
4408 +               }
4409 +
4410                 public static void Error_AddressOfCapturedVar (string name, Location loc)
4411                 {
4412                         Report.Error (1686, loc,
4413 -                               "Local variable `{0}' or its members cannot have their address taken and be used inside an anonymous method block",
4414 -                               name);
4415 +                                     "Local variable `{0}' or its members cannot have their " +
4416 +                                     "address taken and be used inside an anonymous method block",
4417 +                                     name);
4418                 }
4419         }
4420  
4421 @@ -573,138 +1186,84 @@
4422                 
4423                 public override void Emit (EmitContext ec)
4424                 {
4425 -                       if (!am.EmitMethod (ec))
4426 -                               return;
4427 +                       Report.Debug (64, "ANONYMOUS DELEGATE", this, am, ec.ContainerType, type,
4428 +                                     ec, loc);
4429  
4430                         //
4431                         // Now emit the delegate creation.
4432                         //
4433 -                       if ((am.method.ModFlags & Modifiers.STATIC) == 0)
4434 -                               delegate_instance_expression = new AnonymousInstance (am);
4435 -                       
4436 +                       if ((am.Method.ModFlags & Modifiers.STATIC) == 0) {
4437 +                               delegate_instance_expression = am.RootScope.GetScopeInitializer (ec);
4438 +
4439 +                               if (delegate_instance_expression == null)
4440 +                                       throw new InternalErrorException ();
4441 +                       }
4442 +
4443                         Expression ml = Expression.MemberLookup (ec.ContainerType, type, ".ctor", loc);
4444                         constructor_method = ((MethodGroupExpr) ml).Methods [0];
4445 -                       delegate_method = am.GetMethodBuilder ();
4446 +                       delegate_method = am.GetMethodBuilder (ec);
4447 +                       Report.Debug (64, "ANONYMOUS DELEGATE #1", constructor_method, delegate_method,
4448 +                                     delegate_method, delegate_instance_expression);
4449                         base.Emit (ec);
4450                 }
4451 -
4452 -               class AnonymousInstance : Expression {
4453 -                       AnonymousMethod am;
4454 -                       
4455 -                       public AnonymousInstance (AnonymousMethod am)
4456 -                       {
4457 -                               this.am = am;
4458 -                               eclass = ExprClass.Value;
4459 -                       }
4460 -
4461 -                       public override Expression DoResolve (EmitContext ec)
4462 -                       {
4463 -                               return this;
4464 -                       }
4465 -                       
4466 -                       public override void Emit (EmitContext ec)
4467 -                       {
4468 -                               am.aec.EmitMethodHostInstance (ec, am);
4469 -                       }
4470 -               }
4471         }
4472  
4473 -       class CapturedParameter {
4474 -               public Type Type;
4475 -               public FieldBuilder FieldBuilder;
4476 -               public int Idx;
4477 -
4478 -               public CapturedParameter (Type type, int idx)
4479 -               {
4480 -                       Type = type;
4481 -                       Idx = idx;
4482 -               }
4483 -       }
4484 -
4485         //
4486         // Here we cluster all the variables captured on a given scope, we also
4487         // keep some extra information that might be required on each scope.
4488         //
4489 -       public class ScopeInfo {
4490 -               public CaptureContext CaptureContext;
4491 -               public ScopeInfo ParentScope;
4492 -               public Block ScopeBlock;
4493 -               public bool NeedThis = false;
4494 -               public bool HostsParameters = false;
4495 -               
4496 +       public class ScopeInfo : ScopeInfoBase {
4497 +               public readonly AnonymousMethodHost RootScope;
4498 +
4499                 // For tracking the number of scopes created.
4500                 public int id;
4501                 static int count;
4502 -               bool inited = false;
4503                 
4504 -               ArrayList locals = new ArrayList ();
4505 -               ArrayList children = new ArrayList ();
4506 +               Hashtable locals = new Hashtable ();
4507  
4508 -               //
4509 -               // The types and fields generated
4510 -               //
4511 -               public TypeBuilder ScopeTypeBuilder;
4512 -               public Type ScopeType;
4513 -               public ConstructorInfo ScopeConstructor;
4514 -               public FieldBuilder THIS;
4515 -               public FieldBuilder ParentLink;
4516 -
4517 -               //
4518 -               // Points to the object of type `ScopeTypeBuilder' that
4519 -               // holds the data for the scope
4520 -               //
4521 -               LocalBuilder scope_instance;
4522 -               
4523 -               public ScopeInfo (CaptureContext cc, Block b)
4524 +               public ScopeInfo (AnonymousMethodHost root, Block block)
4525 +                       : base (root, null, Modifiers.PUBLIC, block.StartLocation)
4526                 {
4527 -                       CaptureContext = cc;
4528 -                       ScopeBlock = b;
4529 +                       this.RootScope = root;
4530 +                       ScopeBlock = block;
4531                         id = count++;
4532  
4533 -                       cc.RegisterCaptureContext ();
4534 +                       Report.Debug (64, "NEW SCOPE", this);
4535 +
4536 +                       root.AddScope (this);
4537                 }
4538  
4539 -               public void AddLocal (LocalInfo li)
4540 +               public ScopeInfo (ToplevelBlock toplevel, TypeContainer parent,
4541 +                                 GenericMethod generic, Location loc)
4542 +                       : base (parent, generic, 0, loc)
4543                 {
4544 -                       if (locals.Contains (li))
4545 -                               return;
4546 +                       RootScope = (AnonymousMethodHost) this;
4547 +                       ScopeBlock = toplevel;
4548 +                       id = count++;
4549  
4550 -                       locals.Add (li);
4551 -}
4552 -       
4553 -               public bool IsCaptured (LocalInfo li)
4554 -               {
4555 -                       return locals.Contains (li);
4556 +                       Report.Debug (64, "NEW ROOT SCOPE", this);
4557                 }
4558 -               
4559 -               internal void AddChild (ScopeInfo si)
4560 -               {
4561 -                       if (children.Contains (si))
4562 -                               return;
4563  
4564 -                       //
4565 -                       // If any of the current children should be a children of `si', move them there
4566 -                       //
4567 -                       ArrayList move_queue = null;
4568 -                       foreach (ScopeInfo child in children){
4569 -                               if (child.ScopeBlock.IsChildOf (si.ScopeBlock)){
4570 -                                       if (move_queue == null)
4571 -                                               move_queue = new ArrayList ();
4572 -                                       move_queue.Add (child);
4573 -                                       child.ParentScope = si;
4574 -                                       si.AddChild (child);
4575 -                               }
4576 -                       }
4577 -                       
4578 -                       children.Add (si);
4579 +               public override AnonymousMethodHost Host {
4580 +                       get { return RootScope; }
4581 +               }
4582  
4583 -                       if (move_queue != null){
4584 -                               foreach (ScopeInfo child in move_queue){
4585 -                                       children.Remove (child);
4586 -                               }
4587 +               public Variable AddLocal (LocalInfo local)
4588 +               {
4589 +                       Variable var = (Variable) locals [local];
4590 +                       if (var == null) {
4591 +                               var = new CapturedLocal (this, local);
4592 +                               locals.Add (local, var);
4593 +                               local.IsCaptured = true;
4594                         }
4595 -               } 
4596 +                       return var;
4597 +               }
4598  
4599 +               public Variable GetCapturedVariable (LocalInfo local)
4600 +               {
4601 +                       return (Variable) locals [local];
4602 +               }
4603 +
4604                 static int indent = 0;
4605  
4606                 void Pad ()
4607 @@ -719,204 +1278,28 @@
4608                         Pad ();
4609                         Console.WriteLine ("START");
4610                         indent++;
4611 -                       Pad ();
4612 -                       Console.WriteLine ("NeedThis=" + NeedThis);
4613 -                       foreach (LocalInfo li in locals){
4614 +                       foreach (LocalInfo li in locals.Values){
4615                                 Pad ();
4616                                 Console.WriteLine ("var {0}", MakeFieldName (li.Name));
4617                         }
4618                         
4619 -                       foreach (ScopeInfo si in children)
4620 -                               si.EmitDebug ();
4621                         indent--;
4622                         Pad ();
4623                         Console.WriteLine ("END");
4624                 }
4625  
4626 -               private string MakeFieldName (string local_name)
4627 +               protected string MakeFieldName (string local_name)
4628                 {
4629                         return "<" + id + ":" + local_name + ">";
4630                 }
4631  
4632 -               public void EmitScopeType (EmitContext ec)
4633 +               protected override ScopeInitializerBase CreateScopeInitializer ()
4634                 {
4635 -                       // EmitDebug ();
4636 -
4637 -                       if (ScopeTypeBuilder != null)
4638 -                               return;
4639 -                       
4640 -                       Type container;
4641 -                       if (ec.TypeContainer.CurrentType != null)
4642 -                               container = ec.TypeContainer.CurrentType;
4643 -                       else
4644 -                               container = ec.TypeContainer.TypeBuilder;
4645 -
4646 -                       CaptureContext.Host.CreateScopeType (ec, this);
4647 -                       
4648 -                       if (NeedThis)
4649 -                               THIS = ScopeTypeBuilder.DefineField ("<>THIS", container, FieldAttributes.Assembly);
4650 -
4651 -                       if (ParentScope != null){
4652 -                               if (ParentScope.ScopeTypeBuilder == null){
4653 -                                       throw new Exception (String.Format ("My parent has not been initialized {0} and {1}", ParentScope, this));
4654 -                               }
4655 -
4656 -                               if (ParentScope.ScopeTypeBuilder != ScopeTypeBuilder)
4657 -                                       ParentLink = ScopeTypeBuilder.DefineField (
4658 -                                               "<>parent", ParentScope.ScopeType, FieldAttributes.Assembly);
4659 -                       }
4660 -                       
4661 -                       if (NeedThis && ParentScope != null)
4662 -                               throw new Exception ("I was not expecting THIS && having a parent");
4663 -
4664 -                       foreach (LocalInfo info in locals)
4665 -                               info.FieldBuilder = ScopeTypeBuilder.DefineField (
4666 -                                       MakeFieldName (info.Name), info.VariableType, FieldAttributes.Assembly);
4667 -
4668 -                       if (HostsParameters){
4669 -                               Hashtable captured_parameters = CaptureContext.captured_parameters;
4670 -                               
4671 -                               foreach (DictionaryEntry de in captured_parameters){
4672 -                                       string name = (string) de.Key;
4673 -                                       CapturedParameter cp = (CapturedParameter) de.Value;
4674 -                                       FieldBuilder fb;
4675 -                                       
4676 -                                       fb = ScopeTypeBuilder.DefineField ("<p:" + name + ">", cp.Type, FieldAttributes.Assembly);
4677 -                                       cp.FieldBuilder = fb;
4678 -                               }
4679 -                       }
4680 -
4681 -                       foreach (ScopeInfo si in children){
4682 -                               si.EmitScopeType (ec);
4683 -                       }
4684 +                       return new ScopeInitializer (this);
4685                 }
4686  
4687 -               public void CloseTypes ()
4688 -               {
4689 -                       RootContext.RegisterCompilerGeneratedType (ScopeTypeBuilder);
4690 -                       foreach (ScopeInfo si in children)
4691 -                               si.CloseTypes ();
4692 -               }
4693 -
4694 -               //
4695 -               // Emits the initialization code for the scope
4696 -               //
4697 -               public void EmitInitScope (EmitContext ec)
4698 -               {
4699 -                       ILGenerator ig = ec.ig;
4700 -
4701 -                       if (inited)
4702 -                               return;
4703 -
4704 -                       if (ScopeConstructor == null)
4705 -                               throw new Exception ("ScopeConstructor is null for" + this.ToString ());
4706 -                       
4707 -                       if (!CaptureContext.Host.IsIterator) {
4708 -                               scope_instance = ig.DeclareLocal (ScopeType);
4709 -                               ig.Emit (OpCodes.Newobj, ScopeConstructor);
4710 -                               ig.Emit (OpCodes.Stloc, scope_instance);
4711 -                       }
4712 -
4713 -                       if (THIS != null){
4714 -                               if (CaptureContext.Host.IsIterator) {
4715 -                                       ig.Emit (OpCodes.Ldarg_0);
4716 -                                       ig.Emit (OpCodes.Ldarg_1);
4717 -                               } else {
4718 -                                       ig.Emit (OpCodes.Ldloc, scope_instance);
4719 -                                       ig.Emit (OpCodes.Ldarg_0);
4720 -                               }
4721 -                               ig.Emit (OpCodes.Stfld, THIS);
4722 -                       }
4723 -
4724 -                       //
4725 -                       // Copy the parameter values, if any
4726 -                       //
4727 -                       int extra = ec.IsStatic ? 0 : 1;
4728 -                       if (CaptureContext.Host.IsIterator)
4729 -                               extra++;
4730 -                       if (HostsParameters){
4731 -                               Hashtable captured_parameters = CaptureContext.captured_parameters;
4732 -                               
4733 -                               foreach (DictionaryEntry de in captured_parameters){
4734 -                                       CapturedParameter cp = (CapturedParameter) de.Value;
4735 -
4736 -                                       EmitScopeInstance (ig);
4737 -                                       ParameterReference.EmitLdArg (ig, cp.Idx + extra);
4738 -                                       ig.Emit (OpCodes.Stfld, cp.FieldBuilder);
4739 -                               }
4740 -                       }
4741 -
4742 -                       if (ParentScope != null){
4743 -                               if (!ParentScope.inited)
4744 -                                       ParentScope.EmitInitScope (ec);
4745 -
4746 -                               if (ParentScope.ScopeTypeBuilder != ScopeTypeBuilder) {
4747 -                                       //
4748 -                                       // Only emit initialization in our capturecontext world
4749 -                                       //
4750 -                                       if (ParentScope.CaptureContext == CaptureContext){
4751 -                                               EmitScopeInstance (ig);
4752 -                                               ParentScope.EmitScopeInstance (ig);
4753 -                                               ig.Emit (OpCodes.Stfld, ParentLink);
4754 -                                       } else {
4755 -                                               EmitScopeInstance (ig);
4756 -                                               ig.Emit (OpCodes.Ldarg_0);
4757 -                                               ig.Emit (OpCodes.Stfld, ParentLink);
4758 -                                       }
4759 -                               }
4760 -                       }
4761 -                       inited = true;
4762 -               }
4763 -
4764 -               public void EmitScopeInstance (ILGenerator ig)
4765 -               {
4766 -                       if (CaptureContext.Host.IsIterator)
4767 -                               ig.Emit (OpCodes.Ldarg_0);
4768 -                       else {
4769 -                               if (scope_instance == null){
4770 -                                       //
4771 -                                       // This is needed if someone overwrites the Emit method
4772 -                                       // of Statement and manually calls Block.Emit without
4773 -                                       // this snippet first:
4774 -                                       // 
4775 -                                       //   ec.EmitScopeInitFromBlock (The_Block);
4776 -                                       //   The_Block.Emit (ec);
4777 -                                       // 
4778 -
4779 -                                       Console.WriteLine (
4780 -                                               "The scope_instance has not been emitted, this typically means\n" +
4781 -                                               "that inside the compiler someone is calling Block.Emit without\n" +
4782 -                                               "first calling EmitScopeInitFromBlock for the block.  See compiler" +
4783 -                                               "source code for an explanation");
4784 -                                       throw new Exception ("Internal compiler error");
4785 -                                       
4786 -                               }
4787 -                               ig.Emit (OpCodes.Ldloc, scope_instance);
4788 -                       }
4789 -               }
4790 -
4791 -               public static void CheckCycles (string msg, ScopeInfo s)
4792 -               {
4793 -                       ArrayList l = new ArrayList ();
4794 -                       int n = 0;
4795 -                       
4796 -                       for (ScopeInfo p = s; p != null; p = p.ParentScope,n++){
4797 -                               if (l.Contains (p)){
4798 -                                       Console.WriteLine ("Loop detected {0} in {1}", n, msg);
4799 -                                       throw new Exception ();
4800 -                               }
4801 -                               l.Add (p);
4802 -                       }
4803 -               }
4804 -               
4805                 static void DoPath (StringBuilder sb, ScopeInfo start)
4806                 {
4807 -                       CheckCycles ("print", start);
4808 -                       
4809 -                       if (start.ParentScope != null){
4810 -                               DoPath (sb, start.ParentScope);
4811 -                               sb.Append (", ");
4812 -                       }
4813                         sb.Append ((start.id).ToString ());
4814                 }
4815                 
4816 @@ -925,614 +1308,146 @@
4817                         StringBuilder sb = new StringBuilder ();
4818                         
4819                         sb.Append ("{");
4820 -                       if (CaptureContext != null){
4821 -                               sb.Append (CaptureContext.ToString ());
4822 -                               sb.Append (":");
4823 -                       }
4824  
4825                         DoPath (sb, this);
4826                         sb.Append ("}");
4827  
4828                         return sb.ToString ();
4829                 }
4830 -       }
4831  
4832 -       //
4833 -       // CaptureContext objects are created on demand if a method has
4834 -       // anonymous methods and kept on the ToplevelBlock.
4835 -       //
4836 -       // If they exist, all ToplevelBlocks in the containing block are
4837 -       // linked together (children pointing to their parents).
4838 -       //
4839 -       public class CaptureContext {
4840 -               public static int count;
4841 -               public int cc_id;
4842 -               public Location loc;
4843 -               
4844 -               //
4845 -               // Points to the toplevel block that owns this CaptureContext
4846 -               //
4847 -               ToplevelBlock toplevel_owner;
4848 -
4849 -               //
4850 -               // All the scopes we capture
4851 -               //
4852 -               Hashtable scopes = new Hashtable ();
4853 -
4854 -               //
4855 -               // All the root scopes
4856 -               //
4857 -               ArrayList roots = new ArrayList ();
4858 -               
4859 -               bool have_captured_vars = false;
4860 -               bool referenced_this = false;
4861 -
4862 -               //
4863 -               // Captured fields
4864 -               //
4865 -               Hashtable captured_fields = new Hashtable ();
4866 -               Hashtable captured_variables = new Hashtable ();
4867 -               public Hashtable captured_parameters = new Hashtable ();
4868 -               public AnonymousContainer Host;
4869 -               
4870 -               public CaptureContext (ToplevelBlock toplevel_owner, Location loc,
4871 -                                      AnonymousContainer host)
4872 +               protected abstract class CapturedLocalOrParameter : Variable
4873                 {
4874 -                       cc_id = count++;
4875 -                       this.toplevel_owner = toplevel_owner;
4876 -                       this.loc = loc;
4877 +                       public readonly ScopeInfo Scope;
4878 +                       public readonly Field Field;
4879  
4880 -                       if (host != null)
4881 -                               Host = host;
4882 -               }
4883 +                       public FieldExpr FieldInstance;
4884  
4885 -               void DoPath (StringBuilder sb, CaptureContext cc)
4886 -               {
4887 -                       if (cc.ParentCaptureContext != null){
4888 -                               DoPath (sb, cc.ParentCaptureContext);
4889 -                               sb.Append (".");
4890 +                       protected CapturedLocalOrParameter (ScopeInfo scope, string name, Type type)
4891 +                       {
4892 +                               this.Scope = scope;
4893 +                               this.Field = scope.CaptureVariable (
4894 +                                       scope.MakeFieldName (name), type);
4895                         }
4896 -                       sb.Append (cc.cc_id.ToString ());
4897 -               }
4898  
4899 -               public void ReParent (ToplevelBlock new_toplevel, AnonymousContainer new_host)
4900 -               {
4901 -                       toplevel_owner = new_toplevel;
4902 -                       Host = new_host;
4903 -
4904 -                       for (CaptureContext cc = ParentCaptureContext; cc != null;
4905 -                            cc = cc.ParentCaptureContext) {
4906 -                               cc.Host = new_host;
4907 +                       public override Type Type {
4908 +                               get { return Field.MemberType; }
4909                         }
4910 -               }
4911 -               
4912 -               public override string ToString ()
4913 -               {
4914 -                       StringBuilder sb = new StringBuilder ();
4915 -                       sb.Append ("[");
4916 -                       DoPath (sb, this);
4917 -                       sb.Append ("]");
4918 -                       return sb.ToString ();
4919 -               }
4920  
4921 -               public ToplevelBlock ParentToplevel {
4922 -                       get {
4923 -                               return toplevel_owner.Container;
4924 +                       public override bool HasInstance {
4925 +                               get { return true; }
4926                         }
4927 -               }
4928  
4929 -               public CaptureContext ParentCaptureContext {
4930 -                       get {
4931 -                               ToplevelBlock parent = ParentToplevel;
4932 -                               
4933 -                               return (parent == null) ? null : parent.CaptureContext;
4934 +                       public override bool NeedsTemporary {
4935 +                               get { return true; }
4936                         }
4937 -               }
4938  
4939 -               ScopeInfo GetScopeForBlock (Block block)
4940 -               {
4941 -                       ScopeInfo si = (ScopeInfo) scopes [block.ID];
4942 -                       if (si != null)
4943 -                               return si;
4944 -                       si = new ScopeInfo (this, block);
4945 -                       scopes [block.ID] = si;
4946 -                       return si;
4947 -               }
4948 -               
4949 -               public void AddLocal (AnonymousContainer am, LocalInfo li)
4950 -               {
4951 -                       if (li.Block.Toplevel != toplevel_owner){
4952 -                               ParentCaptureContext.AddLocal (am, li);
4953 -                               return;
4954 +                       protected FieldInfo GetField (EmitContext ec)
4955 +                       {
4956 +                               if (ec.CurrentBlock.Toplevel != Scope.ScopeBlock.Toplevel)
4957 +                                       return Field.FieldBuilder;
4958 +                               else
4959 +                                       return FieldInstance.FieldInfo;
4960                         }
4961 -                       ScopeInfo scope = GetScopeForBlock (li.Block);
4962  
4963 -                       //
4964 -                       // Adjust the owner
4965 -                       //
4966 -                       if (Host != null)
4967 -                               Host.RegisterScope (scope);
4968 -
4969 -                       //
4970 -                       // Adjust the user
4971 -                       //
4972 -                       am.RegisterScope (scope);
4973 -                       
4974 -                       if (captured_variables [li] != null)
4975 -                               return;
4976 -                       
4977 -                       have_captured_vars = true;
4978 -                       captured_variables [li] = li;
4979 -                       scope.AddLocal (li);
4980 -               }
4981 -
4982 -               //
4983 -               // Retursn the CaptureContext for the block that defines the parameter `name'
4984 -               //
4985 -               static CaptureContext _ContextForParameter (ToplevelBlock current, string name)
4986 -               {
4987 -                       ToplevelBlock container = current.Container;
4988 -                       if (container != null){
4989 -                               CaptureContext cc = _ContextForParameter (container, name);
4990 -                               if (cc != null)
4991 -                                       return cc;
4992 +                       public override void EmitInstance (EmitContext ec)
4993 +                       {
4994 +                               ec.CurrentBlock.Toplevel.EmitScopeInstance (ec, Scope);
4995                         }
4996 -                       if (current.IsParameterReference (name))
4997 -                               return current.ToplevelBlockCaptureContext;
4998 -                       return null;
4999 -               }
5000  
5001 -               static CaptureContext ContextForParameter (ToplevelBlock current, string name)
5002 -               {
5003 -                       CaptureContext cc = _ContextForParameter (current, name);
5004 -                       if (cc == null)
5005 -                               throw new Exception (String.Format ("request for parameteter {0} failed: not found", name));
5006 -                       return cc;
5007 -               }
5008 -               
5009 -               //
5010 -               // Records the captured parameter at the appropriate CaptureContext
5011 -               //
5012 -               public void AddParameter (EmitContext ec, AnonymousContainer am,
5013 -                                         string name, Type t, int idx)
5014 -               {
5015 -                       CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
5016 -
5017 -                       cc.AddParameterToContext (am, name, t, idx);
5018 -               }
5019 -
5020 -               //
5021 -               // Records the parameters in the context
5022 -               //
5023 -               public void AddParameterToContext (AnonymousContainer am, string name, Type t, int idx)
5024 -               {
5025 -                       if (captured_parameters == null)
5026 -                               captured_parameters = new Hashtable ();
5027 -                       if (captured_parameters [name] == null)
5028 -                               captured_parameters [name] = new CapturedParameter (t, idx);
5029 -
5030 -                       ScopeInfo scope = GetScopeForBlock (toplevel_owner);
5031 -                       scope.HostsParameters = true;
5032 -                       am.RegisterScope (scope);
5033 -               }
5034 -
5035 -               //
5036 -               // Captured fields are only recorded on the topmost CaptureContext, because that
5037 -               // one is the one linked to the owner of instance fields
5038 -               //
5039 -               public void AddField (EmitContext ec, AnonymousContainer am, FieldExpr fe)
5040 -               {
5041 -                       if (fe.FieldInfo.IsStatic)
5042 -                               throw new Exception ("Attempt to register a static field as a captured field");
5043 -                       CaptureContext parent = ParentCaptureContext;
5044 -                       if (parent != null) {
5045 -                               parent.AddField (ec, am, fe);
5046 -                               return;
5047 +                       public override void Emit (EmitContext ec)
5048 +                       {
5049 +                               ec.ig.Emit (OpCodes.Ldfld, GetField (ec));
5050                         }
5051  
5052 -                       ScopeInfo scope = GetScopeForBlock (toplevel_owner);
5053 -                       am.RegisterScope (scope);
5054 -               }
5055 -
5056 -               public void CaptureThis (AnonymousContainer am)
5057 -               {
5058 -                       if (am == null)
5059 -                               throw new Exception ("Internal Compiler error: Capturethis called with a null method");
5060 -                       CaptureContext parent = ParentCaptureContext;
5061 -                       if (parent != null) {
5062 -                               parent.CaptureThis (am);
5063 -                               return;
5064 +                       public override void EmitAssign (EmitContext ec)
5065 +                       {
5066 +                               ec.ig.Emit (OpCodes.Stfld, GetField (ec));
5067                         }
5068 -                       referenced_this = true;
5069  
5070 -                       ScopeInfo scope = GetScopeForBlock (toplevel_owner);
5071 -                       am.RegisterScope (scope);
5072 -               }
5073 -
5074 -               public bool HaveCapturedVariables {
5075 -                       get {
5076 -                               return have_captured_vars;
5077 +                       public override void EmitAddressOf (EmitContext ec)
5078 +                       {
5079 +                               ec.ig.Emit (OpCodes.Ldflda, GetField (ec));
5080                         }
5081                 }
5082 -               
5083 -               public bool HaveCapturedFields {
5084 -                       get {
5085 -                               CaptureContext parent = ParentCaptureContext;
5086 -                               if (parent != null)
5087 -                                       return parent.HaveCapturedFields;
5088 -                               return captured_fields.Count > 0;
5089 -                       }
5090 -               }
5091  
5092 -               public bool IsCaptured (LocalInfo local)
5093 -               {
5094 -                       foreach (ScopeInfo si in scopes.Values){
5095 -                               if (si.IsCaptured (local))
5096 -                                       return true;
5097 -                       }
5098 -                       return false;
5099 -               }
5100 +               protected class CapturedParameter : CapturedLocalOrParameter {
5101 +                       public readonly Parameter Parameter;
5102 +                       public readonly int Idx;
5103  
5104 -               //
5105 -               // Returns whether the parameter is captured
5106 -               //
5107 -               public bool IsParameterCaptured (string name)
5108 -               {
5109 -                       if (ParentCaptureContext != null && ParentCaptureContext.IsParameterCaptured (name))
5110 -                               return true;
5111 -                       
5112 -                       if (captured_parameters != null)
5113 -                               return captured_parameters [name] != null;
5114 -                       return false;
5115 -               }
5116 -
5117 -               public void EmitAnonymousHelperClasses (EmitContext ec)
5118 -               {
5119 -                       if (roots.Count != 0){
5120 -                               foreach (ScopeInfo root in roots){
5121 -                                       //
5122 -                                       // FIXME: We really should do this in a per-ScopeInfo
5123 -                                       // basis, instead of having the NeedThis applied to
5124 -                                       // all of the roots.
5125 -                                       //
5126 -                                       root.NeedThis = HaveCapturedFields || referenced_this;
5127 -                                       
5128 -                                       root.EmitScopeType (ec);
5129 -                               }
5130 -                       } 
5131 -               }
5132 -
5133 -               public void CloseAnonymousHelperClasses ()
5134 -               {
5135 -                       if (roots.Count != 0)
5136 -                               foreach (ScopeInfo root in roots)
5137 -                                       root.CloseTypes ();
5138 -               }
5139 -
5140 -               public void EmitInitScope (EmitContext ec)
5141 -               {
5142 -                       EmitAnonymousHelperClasses (ec);
5143 -                       if (roots.Count != 0)
5144 -                               foreach (ScopeInfo root in roots)
5145 -                                       root.EmitInitScope (ec);                }
5146 -
5147 -               //
5148 -               // This is called externally when we start emitting code for a block
5149 -               // if the block has a ScopeInfo associated, emit the init code
5150 -               //
5151 -               public void EmitScopeInitFromBlock (EmitContext ec, Block b)
5152 -               {
5153 -                       ScopeInfo si = (ScopeInfo) scopes [b.ID];
5154 -                       if (si == null)
5155 -                               return;
5156 -
5157 -                       si.EmitInitScope (ec);
5158 -               }
5159 -               
5160 -               //
5161 -               // Emits the opcodes necessary to load the instance of the captured
5162 -               // variable in `li'
5163 -               //
5164 -               public void EmitCapturedVariableInstance (EmitContext ec, LocalInfo li,
5165 -                                                         AnonymousContainer am)
5166 -               {
5167 -                       ILGenerator ig = ec.ig;
5168 -                       ScopeInfo si;
5169 -
5170 -                       if (li.Block.Toplevel == toplevel_owner){
5171 -                               si = (ScopeInfo) scopes [li.Block.ID];
5172 -                               si.EmitScopeInstance (ig);
5173 -                               return;
5174 +                       public CapturedParameter (ScopeInfo scope, Parameter par, int idx)
5175 +                               : base (scope, par.Name, par.ParameterType)
5176 +                       {
5177 +                               this.Parameter = par;
5178 +                               this.Idx = idx;
5179                         }
5180  
5181 -                       si = am.Scope;
5182 -                       ig.Emit (OpCodes.Ldarg_0);
5183 -                       if (si != null){
5184 -                               if (am.IsIterator && (si.ScopeBlock.Toplevel == li.Block.Toplevel)) {
5185 -                                       return;
5186 -                               }
5187 -
5188 -                               while (si.ScopeBlock.ID != li.Block.ID){
5189 -                                       if (si.ParentLink != null)
5190 -                                               ig.Emit (OpCodes.Ldfld, si.ParentLink);
5191 -                                       si = si.ParentScope;
5192 -                                       if (si == null) {
5193 -                                               si = am.Scope;
5194 -                                               Console.WriteLine ("Target: {0} {1}", li.Block.ID, li.Name);
5195 -                                               while (si.ScopeBlock.ID != li.Block.ID){
5196 -                                                       Console.WriteLine ("Trying: {0}", si.ScopeBlock.ID);
5197 -                                                       si = si.ParentScope;
5198 -                                               }
5199 -
5200 -                                               throw new Exception (
5201 -                                                            String.Format ("Never found block {0} starting at {1} while looking up {2}",
5202 -                                                                           li.Block.ID, am.Scope.ScopeBlock.ID, li.Name));
5203 -                                       }
5204 -                               }
5205 +                       public override string ToString ()
5206 +                       {
5207 +                               return String.Format ("{0} ({1}:{2}:{3})", GetType (), Field,
5208 +                                                     Parameter.Name, Idx);
5209                         }
5210                 }
5211  
5212 -               //
5213 -               // Internal routine that loads the instance to reach parameter `name'
5214 -               //
5215 -               void EmitParameterInstance (EmitContext ec, string name)
5216 -               {
5217 -                       CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
5218 -                       if (cc != this){
5219 -                               cc.EmitParameterInstance (ec, name);
5220 -                               return;
5221 -                       }
5222 +               protected class CapturedLocal : CapturedLocalOrParameter {
5223 +                       public readonly LocalInfo Local;
5224  
5225 -                       CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
5226 -                       if (par_info != null){
5227 -                               // 
5228 -                               // FIXME: implementing this.
5229 -                               //
5230 +                       public CapturedLocal (ScopeInfo scope, LocalInfo local)
5231 +                               : base (scope, local.Name, local.VariableType)
5232 +                       {
5233 +                               this.Local = local;
5234                         }
5235 -                       ILGenerator ig = ec.ig;
5236  
5237 -                       ScopeInfo si;
5238 -
5239 -                       if (ec.CurrentBlock.Toplevel == toplevel_owner) {
5240 -                               si = (ScopeInfo) scopes [toplevel_owner.ID];
5241 -                               si.EmitScopeInstance (ig);
5242 -                       } else {
5243 -                               si = ec.CurrentAnonymousMethod.Scope;
5244 -                               ig.Emit (OpCodes.Ldarg_0);
5245 +                       public override string ToString ()
5246 +                       {
5247 +                               return String.Format ("{0} ({1}:{2})", GetType (), Field,
5248 +                                                     Local.Name);
5249                         }
5250 -
5251 -                       if (si != null){
5252 -                               while (si.ParentLink != null) {
5253 -                                       ig.Emit (OpCodes.Ldfld, si.ParentLink);
5254 -                                       si = si.ParentScope;
5255 -                               } 
5256 -                       }
5257                 }
5258  
5259 -               //
5260 -               // Emits the code necessary to load the parameter named `name' within
5261 -               // an anonymous method.
5262 -               //
5263 -               public void EmitParameter (EmitContext ec, string name, bool leave_copy, bool prepared, ref LocalTemporary temp)
5264 +               protected class ScopeInitializer : ScopeInitializerBase
5265                 {
5266 -                       CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
5267 -                       if (cc != this){
5268 -                               cc.EmitParameter (ec, name, leave_copy, prepared, ref temp);
5269 -                               return;
5270 -                       }
5271 -                       if (!prepared)
5272 -                               EmitParameterInstance (ec, name);
5273 -                       CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
5274 -                       if (par_info != null){
5275 -                               // 
5276 -                               // FIXME: implementing this.
5277 -                               //
5278 -                       }
5279 -                       ec.ig.Emit (OpCodes.Ldfld, par_info.FieldBuilder);
5280 +                       ScopeInfo scope;
5281  
5282 -                       if (leave_copy){
5283 -                               ec.ig.Emit (OpCodes.Dup);
5284 -                               temp = new LocalTemporary (par_info.FieldBuilder.FieldType);
5285 -                               temp.Store (ec);
5286 +                       public ScopeInitializer (ScopeInfo scope)
5287 +                               : base (scope)
5288 +                       {
5289 +                               this.scope = scope;
5290                         }
5291 -               }
5292  
5293 -               //
5294 -               // Implements the assignment of `source' to the paramenter named `name' within
5295 -               // an anonymous method.
5296 -               //
5297 -               public void EmitAssignParameter (EmitContext ec, string name, Expression source, bool leave_copy, bool prepare_for_load, ref LocalTemporary temp)
5298 -               {
5299 -                       CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
5300 -                       if (cc != this){
5301 -                               cc.EmitAssignParameter (ec, name, source, leave_copy, prepare_for_load, ref temp);
5302 -                               return;
5303 +                       new public ScopeInfo Scope {
5304 +                               get { return scope; }
5305                         }
5306 -                       ILGenerator ig = ec.ig;
5307 -                       CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
5308  
5309 -                       EmitParameterInstance (ec, name);
5310 -                       if (prepare_for_load)
5311 -                               ig.Emit (OpCodes.Dup);
5312 -                       source.Emit (ec);
5313 -                       if (leave_copy){
5314 -                               ig.Emit (OpCodes.Dup);
5315 -                               temp = new LocalTemporary (par_info.FieldBuilder.FieldType);
5316 -                               temp.Store (ec);
5317 -                       }
5318 -                       ig.Emit (OpCodes.Stfld, par_info.FieldBuilder);
5319 -                       if (temp != null)
5320 -                               temp.Emit (ec);
5321 -               }
5322 +                       protected override bool DoResolveInternal (EmitContext ec)
5323 +                       {
5324 +                               Report.Debug (64, "RESOLVE SCOPE INITIALIZER", this, Scope,
5325 +                                             Scope.ScopeType, ec,
5326 +                                             ec.TypeContainer.Name, ec.DeclContainer,
5327 +                                             ec.DeclContainer.Name, ec.DeclContainer.IsGeneric);
5328  
5329 -               //
5330 -               // Emits the address for the parameter named `name' within
5331 -               // an anonymous method.
5332 -               //
5333 -               public void EmitAddressOfParameter (EmitContext ec, string name)
5334 -               {
5335 -                       CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
5336 -                       if (cc != this){
5337 -                               cc.EmitAddressOfParameter (ec, name);
5338 -                               return;
5339 -                       }
5340 -                       EmitParameterInstance (ec, name);
5341 -                       CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
5342 -                       ec.ig.Emit (OpCodes.Ldflda, par_info.FieldBuilder);
5343 -               }
5344 +                               foreach (CapturedLocal local in Scope.locals.Values) {
5345 +                                       FieldExpr fe = (FieldExpr) Expression.MemberLookup (
5346 +                                               ec.ContainerType, type, local.Field.Name, loc);
5347 +                                       Report.Debug (64, "RESOLVE SCOPE INITIALIZER #2", this, Scope,
5348 +                                                     Scope, ec, ec.ContainerType, type,
5349 +                                                     local.Field, local.Field.Name, loc, fe);
5350 +                                       if (fe == null)
5351 +                                               throw new InternalErrorException ();
5352  
5353 -               //
5354 -               // The following methods are only invoked on the host for the
5355 -               // anonymous method.
5356 -               //
5357 -               public void EmitMethodHostInstance (EmitContext target, AnonymousContainer am)
5358 -               {
5359 -                       ILGenerator ig = target.ig;
5360 -                       ScopeInfo si = am.Scope;
5361 -
5362 -                       AnonymousContainer container = am.ContainerAnonymousMethod;
5363 -
5364 -                       if ((si == null) || ((container != null) && (si == container.Scope))) {
5365 -                               ig.Emit (OpCodes.Ldarg_0);
5366 -                               return;
5367 -                       }
5368 -
5369 -                       si.EmitInitScope (target);
5370 -                       si.EmitScopeInstance (ig);
5371 -               }
5372 -
5373 -               public void RegisterCaptureContext ()
5374 -               {
5375 -                       toplevel_owner.RegisterCaptureContext (this);
5376 -               }
5377 -
5378 -               //
5379 -               // Returs true if `probe' is an ancestor of `scope' in the 
5380 -               // scope chain
5381 -               //
5382 -               bool IsAncestor (ScopeInfo probe, ScopeInfo scope)
5383 -               {
5384 -                       for (Block b = scope.ScopeBlock.Parent; b != null; b = b.Parent){
5385 -                               if (probe.ScopeBlock == b)
5386 -                                       return true;
5387 -                       }
5388 -                       return false;
5389 -               }
5390 -
5391 -               //
5392 -               // Returns an ArrayList of ScopeInfos that enumerates all the ancestors
5393 -               // of `scope' found in `scope_list'.
5394 -               //
5395 -               // The value returned is either a ScopeInfo or an Arraylist of ScopeInfos
5396 -               //
5397 -               object GetAncestorScopes (ScopeInfo scope, ScopeInfo [] scope_list)
5398 -               {
5399 -                       object ancestors = null;
5400 -                       
5401 -                       for (int i = 0; i < scope_list.Length; i++){
5402 -                               // Ignore the same scope
5403 -                               if (scope_list [i] == scope)
5404 -                                       continue;
5405 -                               
5406 -                               if (IsAncestor (scope_list [i], scope)){
5407 -                                       if (ancestors == null){
5408 -                                               ancestors = scope_list [i];
5409 -                                               continue;
5410 -                                       }
5411 -                                       
5412 -                                       if (ancestors is ScopeInfo){
5413 -                                               object old = ancestors;
5414 -                                               ancestors = new ArrayList (4);
5415 -                                               ((ArrayList)ancestors).Add (old);
5416 -                                       } 
5417 -                                       
5418 -                                       ((ArrayList)ancestors).Add (scope_list [i]);
5419 +                                       fe.InstanceExpression = this;
5420 +                                       local.FieldInstance = fe;
5421                                 }
5422 -                       }
5423 -                       return ancestors;
5424 -               }
5425  
5426 -               //
5427 -               // Returns the immediate parent of `scope' from all the captured
5428 -               // scopes found in `scope_list', or null if this is a toplevel scope.
5429 -               //
5430 -               ScopeInfo GetParentScope (ScopeInfo scope, ScopeInfo [] scope_list)
5431 -               {
5432 -                       object ancestors = GetAncestorScopes (scope, scope_list);
5433 -                       if (ancestors == null)
5434 -                               return null;
5435 -
5436 -                       // Single match, thats the parent.
5437 -                       if (ancestors is ScopeInfo)
5438 -                               return (ScopeInfo) ancestors;
5439 -
5440 -                       ArrayList candidates = (ArrayList) ancestors;
5441 -                       ScopeInfo parent = (ScopeInfo) candidates [0];
5442 -                       for (int i = 1; i < candidates.Count; i++){
5443 -                               if (IsAncestor (parent, (ScopeInfo) candidates [i]))
5444 -                                       parent = (ScopeInfo) candidates [i];
5445 +                               return base.DoResolveInternal (ec);
5446                         }
5447 -                       return parent;
5448 -               }
5449 -               
5450 -               //
5451 -               // Links all the scopes
5452 -               //
5453 -               bool linked;
5454 -               public void LinkScopes ()
5455 -               {
5456 -                       if (linked)
5457 -                               return;
5458 -                       
5459 -                       linked = true;
5460 -                       if (ParentCaptureContext != null)
5461 -                               ParentCaptureContext.LinkScopes ();
5462  
5463 -                       int scope_count = scopes.Keys.Count;
5464 -                       ScopeInfo [] scope_list = new ScopeInfo [scope_count];
5465 -                       scopes.Values.CopyTo (scope_list, 0);
5466 -
5467 -                       for (int i = 0; i < scope_count; i++){
5468 -                               ScopeInfo parent = GetParentScope (scope_list [i], scope_list);
5469 -
5470 -                               if (parent == null){
5471 -                                       roots.Add (scope_list [i]);
5472 -                                       continue;
5473 -                               }
5474 -
5475 -                               scope_list [i].ParentScope = parent;
5476 -                               parent.AddChild (scope_list [i]);
5477 +                       protected virtual void EmitParameterReference (EmitContext ec,
5478 +                                                                      CapturedParameter cp)
5479 +                       {
5480 +                               int extra = ec.IsStatic ? 0 : 1;
5481 +                               ParameterReference.EmitLdArg (ec.ig, cp.Idx + extra);
5482                         }
5483  
5484 -                       //
5485 -                       // Link the roots to their parent containers if any.
5486 -                       //
5487 -                       if (ParentCaptureContext != null && roots.Count != 0){
5488 -                               ScopeInfo one_root = (ScopeInfo) roots [0];
5489 -                               bool found = false;
5490 -                               
5491 -                               foreach (ScopeInfo a_parent_root in ParentCaptureContext.roots){
5492 -                                       if (!IsAncestor (a_parent_root, one_root))
5493 -                                               continue;
5494 -
5495 -                                       found = true;
5496 -                                       
5497 -                                       // Found, link all the roots to this root
5498 -                                       foreach (ScopeInfo root in roots){
5499 -                                               root.ParentScope = a_parent_root;
5500 -                                               a_parent_root.AddChild (root);
5501 -                                       }
5502 -                                       break;
5503 -                               }
5504 -                               if (!found){
5505 -                                       //
5506 -                                       // This is to catch a condition in which it is
5507 -                                       // not possible to determine the containing ScopeInfo
5508 -                                       // from an encapsulating CaptureContext
5509 -                                       //
5510 -                                       throw new Exception ("Internal compiler error: Did not find the parent for the root in the chain");
5511 -                               }
5512 -                       }
5513                 }
5514         }
5515  }
5516 Index: expression.cs
5517 ===================================================================
5518 --- expression.cs       (revision 63019)
5519 +++ expression.cs       (working copy)
5520 @@ -457,8 +457,7 @@
5521                                 }
5522  
5523                                 ParameterReference pr = Expr as ParameterReference;
5524 -                               if ((pr != null) && (ec.capture_context != null) &&
5525 -                                   ec.capture_context.IsParameterCaptured (pr.Name)) {
5526 +                               if ((pr != null) && pr.Parameter.IsCaptured) {
5527                                         AnonymousMethod.Error_AddressOfCapturedVar (pr.Name, loc);
5528                                         return null;
5529                                 }
5530 @@ -3309,6 +3308,7 @@
5531                 bool is_readonly;
5532                 bool prepared;
5533                 LocalTemporary temp;
5534 +               Variable variable;
5535  
5536                 public LocalVariableReference (Block block, string name, Location l)
5537                 {
5538 @@ -3363,20 +3363,19 @@
5539                         if (!VerifyAssigned (ec))
5540                                 return null;
5541  
5542 -                       if (ec.CurrentAnonymousMethod != null){
5543 -                               //
5544 -                               // If we are referencing a variable from the external block
5545 -                               // flag it for capturing
5546 -                               //
5547 -                               if ((local_info.Block.Toplevel != ec.CurrentBlock.Toplevel) ||
5548 -                                   ec.CurrentAnonymousMethod.IsIterator)
5549 -                               {
5550 -                                       if (local_info.AddressTaken){
5551 -                                               AnonymousMethod.Error_AddressOfCapturedVar (local_info.Name, loc);
5552 -                                               return null;
5553 -                                       }
5554 -                                       ec.CaptureVariable (local_info);
5555 +                       //
5556 +                       // If we are referencing a variable from the external block
5557 +                       // flag it for capturing
5558 +                       //
5559 +                       if (ec.MustCaptureVariable (local_info)) {
5560 +                               if (local_info.AddressTaken){
5561 +                                       AnonymousMethod.Error_AddressOfCapturedVar (local_info.Name, loc);
5562 +                                       return null;
5563                                 }
5564 +
5565 +                               ScopeInfo scope = local_info.Block.CreateScopeInfo ();
5566 +                               variable = scope.AddLocal (local_info);
5567 +                               type = variable.Type;
5568                         }
5569  
5570                         return this;
5571 @@ -3439,90 +3438,57 @@
5572                         return Name == lvr.Name && Block == lvr.Block;
5573                 }
5574  
5575 +               public Variable Variable {
5576 +                       get { return variable != null ? variable : local_info.Variable; }
5577 +               }
5578 +
5579                 public override void Emit (EmitContext ec)
5580                 {
5581 -                       ILGenerator ig = ec.ig;
5582 -
5583 -                       if (local_info.FieldBuilder == null){
5584 -                               //
5585 -                               // A local variable on the local CLR stack
5586 -                               //
5587 -                               ig.Emit (OpCodes.Ldloc, local_info.LocalBuilder);
5588 -                       } else {
5589 -                               //
5590 -                               // A local variable captured by anonymous methods.
5591 -                               //
5592 -                               if (!prepared)
5593 -                                       ec.EmitCapturedVariableInstance (local_info);
5594 -                               
5595 -                               ig.Emit (OpCodes.Ldfld, local_info.FieldBuilder);
5596 -                       }
5597 +                       Report.Debug (64, "EMIT LOCAL VARIABLE REFERENCE", this, ec, Variable, loc);
5598 +                       if (!prepared)
5599 +                               Variable.EmitInstance (ec);
5600 +                       Variable.Emit (ec);
5601                 }
5602                 
5603                 public void Emit (EmitContext ec, bool leave_copy)
5604                 {
5605                         Emit (ec);
5606 -                       if (leave_copy){
5607 +                       if (leave_copy) {
5608                                 ec.ig.Emit (OpCodes.Dup);
5609 -                               if (local_info.FieldBuilder != null){
5610 +                               if (Variable.NeedsTemporary) {
5611                                         temp = new LocalTemporary (Type);
5612                                         temp.Store (ec);
5613                                 }
5614                         }
5615                 }
5616 -               
5617 -               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
5618 +
5619 +               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy,
5620 +                                       bool prepare_for_load)
5621                 {
5622                         ILGenerator ig = ec.ig;
5623                         prepared = prepare_for_load;
5624  
5625 -                       if (local_info.FieldBuilder == null){
5626 -                               //
5627 -                               // A local variable on the local CLR stack
5628 -                               //
5629 -                               if (local_info.LocalBuilder == null)
5630 -                                       throw new Exception ("This should not happen: both Field and Local are null");
5631 -
5632 -                               source.Emit (ec);
5633 -                               if (leave_copy)
5634 -                                       ec.ig.Emit (OpCodes.Dup);
5635 -                               ig.Emit (OpCodes.Stloc, local_info.LocalBuilder);
5636 -                       } else {
5637 -                               //
5638 -                               // A local variable captured by anonymous methods or itereators.
5639 -                               //
5640 -                               ec.EmitCapturedVariableInstance (local_info);
5641 -
5642 -                               if (prepare_for_load)
5643 -                                       ig.Emit (OpCodes.Dup);
5644 -                               source.Emit (ec);
5645 -                               if (leave_copy){
5646 -                                       ig.Emit (OpCodes.Dup);
5647 +                       Report.Debug (64, "LOCAL VAR REF EMIT ASSIGN", this, source, loc);
5648 +                       Variable.EmitInstance (ec);
5649 +                       if (prepare_for_load && Variable.HasInstance)
5650 +                               ig.Emit (OpCodes.Dup);
5651 +                       source.Emit (ec);
5652 +                       if (leave_copy) {
5653 +                               ig.Emit (OpCodes.Dup);
5654 +                               if (Variable.NeedsTemporary) {
5655                                         temp = new LocalTemporary (Type);
5656                                         temp.Store (ec);
5657                                 }
5658 -                               ig.Emit (OpCodes.Stfld, local_info.FieldBuilder);
5659 -                               if (temp != null)
5660 -                                       temp.Emit (ec);
5661                         }
5662 +                       Variable.EmitAssign (ec);
5663 +                       if (temp != null)
5664 +                               temp.Emit (ec);
5665                 }
5666                 
5667                 public void AddressOf (EmitContext ec, AddressOp mode)
5668                 {
5669 -                       ILGenerator ig = ec.ig;
5670 -
5671 -                       if (local_info.FieldBuilder == null){
5672 -                               //
5673 -                               // A local variable on the local CLR stack
5674 -                               //
5675 -                               ig.Emit (OpCodes.Ldloca, local_info.LocalBuilder);
5676 -                       } else {
5677 -                               //
5678 -                               // A local variable captured by anonymous methods or iterators
5679 -                               //
5680 -                               ec.EmitCapturedVariableInstance (local_info);
5681 -                               ig.Emit (OpCodes.Ldflda, local_info.FieldBuilder);
5682 -                       }
5683 +                       Variable.EmitInstance (ec);
5684 +                       Variable.EmitAddressOf (ec);
5685                 }
5686  
5687                 public override string ToString ()
5688 @@ -3561,7 +3527,14 @@
5689                         }
5690                 }
5691  
5692 +               public Parameter Parameter {
5693 +                       get {
5694 +                               return par;
5695 +                       }
5696 +               }
5697 +
5698                 LocalTemporary temp;
5699 +               Variable variable;
5700                 
5701                 public ParameterReference (Parameter par, Block block, int idx, Location loc)
5702                 {
5703 @@ -3577,6 +3550,10 @@
5704                         get { return vi; }
5705                 }
5706  
5707 +               public Variable Variable {
5708 +                       get { return variable != null ? variable : par.Variable; }
5709 +               }
5710 +
5711                 public bool VerifyFixed ()
5712                 {
5713                         // A parameter is fixed if it's a value parameter (i.e., no modifier like out, ref, param).
5714 @@ -3630,23 +3607,33 @@
5715                         if (is_out)
5716                                 vi = block.ParameterMap [idx];
5717  
5718 -                       if (ec.CurrentAnonymousMethod != null){
5719 -                               if (is_ref && !block.Toplevel.IsLocalParameter (name)){
5720 -                                       Report.Error (1628, Location, "Cannot use ref or out parameter `{0}' inside an anonymous method block",
5721 -                                               par.Name);
5722 -                                       return false;
5723 -                               }
5724 +                       AnonymousContainer am = ec.CurrentAnonymousMethod;
5725 +                       if (am == null)
5726 +                               return true;
5727  
5728 -                               //
5729 -                               // If we are referencing the parameter from the external block
5730 -                               // flag it for capturing
5731 -                               //
5732 -                               //Console.WriteLine ("Is parameter `{0}' local? {1}", name, block.IsLocalParameter (name));
5733 -                               if (!block.Toplevel.IsLocalParameter (name)){
5734 -                                       ec.CaptureParameter (name, type, idx);
5735 +                       if (is_ref && !block.Toplevel.IsLocalParameter (name)){
5736 +                               Report.Error (1628, Location,
5737 +                                             "Cannot use ref or out parameter `{0}' inside an " +
5738 +                                             "anonymous method block", par.Name);
5739 +                               return false;
5740 +                       }
5741 +
5742 +                       if (!am.IsIterator && block.Toplevel.IsLocalParameter (name))
5743 +                               return true;
5744 +
5745 +                       AnonymousMethodHost host = null;
5746 +                       ToplevelBlock toplevel = block.Toplevel;
5747 +                       while (toplevel != null) {
5748 +                               if (toplevel.IsLocalParameter (name)) {
5749 +                                       host = toplevel.AnonymousMethodHost;
5750 +                                       break;
5751                                 }
5752 +
5753 +                               toplevel = toplevel.Container;
5754                         }
5755  
5756 +                       variable = host.AddParameter (par, idx);
5757 +                       type = variable.Type;
5758                         return true;
5759                 }
5760  
5761 @@ -3681,7 +3668,8 @@
5762                         if (!DoResolveBase (ec))
5763                                 return null;
5764  
5765 -                       if (is_out && ec.DoFlowAnalysis && (!ec.OmitStructFlowAnalysis || !vi.TypeInfo.IsStruct) && !IsAssigned (ec, loc))
5766 +                       if (is_out && ec.DoFlowAnalysis &&
5767 +                           (!ec.OmitStructFlowAnalysis || !vi.TypeInfo.IsStruct) && !IsAssigned (ec, loc))
5768                                 return null;
5769  
5770                         return this;
5771 @@ -3731,7 +3719,7 @@
5772                         // FIXME: Review for anonymous methods
5773                         //
5774                 }
5775 -               
5776 +
5777                 public override void Emit (EmitContext ec)
5778                 {
5779                         Emit (ec, false);
5780 @@ -3739,19 +3727,10 @@
5781                 
5782                 public void Emit (EmitContext ec, bool leave_copy)
5783                 {
5784 -                       ILGenerator ig = ec.ig;
5785 -                       int arg_idx = idx;
5786 +                       if (!prepared)
5787 +                               Variable.EmitInstance (ec);
5788 +                       Variable.Emit (ec);
5789  
5790 -                       if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){                               
5791 -                               ec.EmitParameter (name, leave_copy, prepared, ref temp);
5792 -                               return;
5793 -                       }
5794 -
5795 -                       if (!ec.MethodIsStatic)
5796 -                               arg_idx++;
5797 -
5798 -                       EmitLdArg (ig, arg_idx);
5799 -
5800                         if (is_ref) {
5801                                 if (prepared)
5802                                         ec.ig.Emit (OpCodes.Dup);
5803 @@ -3760,84 +3739,51 @@
5804                                 // If we are a reference, we loaded on the stack a pointer
5805                                 // Now lets load the real value
5806                                 //
5807 -                               LoadFromPtr (ig, type);
5808 +                               LoadFromPtr (ec.ig, type);
5809                         }
5810 -                       
5811 +
5812                         if (leave_copy) {
5813                                 ec.ig.Emit (OpCodes.Dup);
5814 -                               
5815 -                               if (is_ref) {
5816 -                                       temp = new LocalTemporary (type);
5817 +
5818 +                               if (is_ref || Variable.NeedsTemporary) {
5819 +                                       temp = new LocalTemporary (Type);
5820                                         temp.Store (ec);
5821                                 }
5822                         }
5823                 }
5824 -               
5825 -               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
5826 +
5827 +               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy,
5828 +                                       bool prepare_for_load)
5829                 {
5830 +                       ILGenerator ig = ec.ig;
5831                         prepared = prepare_for_load;
5832 -                       if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
5833 -                               ec.EmitAssignParameter (name, source, leave_copy, prepare_for_load, ref temp);
5834 -                               return;
5835 -                       }
5836  
5837 -                       ILGenerator ig = ec.ig;
5838 -                       int arg_idx = idx;
5839 -                       
5840 -                       
5841 -                       
5842 -                       if (!ec.MethodIsStatic)
5843 -                               arg_idx++;
5844 +                       Variable.EmitInstance (ec);
5845 +                       if (prepare_for_load && Variable.HasInstance)
5846 +                               ig.Emit (OpCodes.Dup);
5847 +                       else if (is_ref)
5848 +                               Variable.Emit (ec);
5849  
5850 -                       if (is_ref && !prepared)
5851 -                               EmitLdArg (ig, arg_idx);
5852 -                       
5853                         source.Emit (ec);
5854 -
5855 -                       if (leave_copy)
5856 -                               ec.ig.Emit (OpCodes.Dup);
5857 -                       
5858 -                       if (is_ref) {
5859 -                               if (leave_copy) {
5860 -                                       temp = new LocalTemporary (type);
5861 +                       if (leave_copy) {
5862 +                               ig.Emit (OpCodes.Dup);
5863 +                               if (Variable.NeedsTemporary) {
5864 +                                       temp = new LocalTemporary (Type);
5865                                         temp.Store (ec);
5866                                 }
5867 -                               
5868 -                               StoreFromPtr (ig, type);
5869 -                               
5870 -                               if (temp != null)
5871 -                                       temp.Emit (ec);
5872 -                       } else {
5873 -                               if (arg_idx <= 255)
5874 -                                       ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
5875 -                               else
5876 -                                       ig.Emit (OpCodes.Starg, arg_idx);
5877                         }
5878 +                       if (is_ref)
5879 +                               StoreFromPtr (ig, type);
5880 +                       else
5881 +                               Variable.EmitAssign (ec);
5882 +                       if (temp != null)
5883 +                               temp.Emit (ec);
5884                 }
5885 -
5886 +               
5887                 public void AddressOf (EmitContext ec, AddressOp mode)
5888                 {
5889 -                       if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
5890 -                               ec.EmitAddressOfParameter (name);
5891 -                               return;
5892 -                       }
5893 -                       
5894 -                       int arg_idx = idx;
5895 -
5896 -                       if (!ec.MethodIsStatic)
5897 -                               arg_idx++;
5898 -
5899 -                       if (is_ref){
5900 -                               if (arg_idx <= 255)
5901 -                                       ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
5902 -                               else
5903 -                                       ec.ig.Emit (OpCodes.Ldarg, arg_idx);
5904 -                       } else {
5905 -                               if (arg_idx <= 255)
5906 -                                       ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
5907 -                               else
5908 -                                       ec.ig.Emit (OpCodes.Ldarga, arg_idx);
5909 -                       }
5910 +                       Variable.EmitInstance (ec);
5911 +                       Variable.EmitAddressOf (ec);
5912                 }
5913  
5914                 public override string ToString ()
5915 @@ -6649,11 +6595,14 @@
5916                                 return false;
5917                         }
5918  
5919 -                       if (block != null && block.Toplevel.ThisVariable != null)
5920 -                               variable_info = block.Toplevel.ThisVariable.VariableInfo;
5921 +                       if (block != null) {
5922 +                               if (block.Toplevel.ThisVariable != null)
5923 +                                       variable_info = block.Toplevel.ThisVariable.VariableInfo;
5924  
5925 -                       if (ec.CurrentAnonymousMethod != null)
5926 -                               ec.CaptureThis ();
5927 +                               AnonymousMethodHost host = block.Toplevel.AnonymousMethodHost;
5928 +                               if (host != null)
5929 +                                       host.CaptureThis ();
5930 +                       }
5931                         
5932                         return true;
5933                 }
5934 Index: codegen.cs
5935 ===================================================================
5936 --- codegen.cs  (revision 63019)
5937 +++ codegen.cs  (working copy)
5938 @@ -9,7 +9,7 @@
5939  //
5940  
5941  #if !DEBUG
5942 -       #define PRODUCTION
5943 +//     #define PRODUCTION
5944  #endif
5945  
5946  using System;
5947 @@ -350,25 +350,13 @@
5948                 /// </summary>
5949                 public bool InEnumContext;
5950  
5951 -               /// <summary>
5952 -               ///   Anonymous methods can capture local variables and fields,
5953 -               ///   this object tracks it.  It is copied from the TopLevelBlock
5954 -               ///   field.
5955 -               /// </summary>
5956 -               public CaptureContext capture_context;
5957 -
5958                 public readonly IResolveContext ResolveContext;
5959  
5960                 /// <summary>
5961                 ///    The current iterator
5962                 /// </summary>
5963                 public Iterator CurrentIterator {
5964 -                       get {
5965 -                               if (CurrentAnonymousMethod != null)
5966 -                                       return CurrentAnonymousMethod.Iterator;
5967 -                               else
5968 -                                       return null;
5969 -                       }
5970 +                       get { return CurrentAnonymousMethod as Iterator; }
5971                 }
5972  
5973                 /// <summary>
5974 @@ -390,8 +378,8 @@
5975  
5976                 public override string ToString ()
5977                 {
5978 -                       return String.Format ("EmitContext ({0}:{1}:{2})", id,
5979 -                                             CurrentIterator, capture_context, loc);
5980 +                       return String.Format ("EmitContext ({0}:{1})", id,
5981 +                                             CurrentAnonymousMethod, loc);
5982                 }
5983                 
5984                 public EmitContext (IResolveContext rc, DeclSpace parent, DeclSpace ds, Location l, ILGenerator ig,
5985 @@ -525,16 +513,6 @@
5986                         get { return current_flow_branching; }
5987                 }
5988  
5989 -               public bool HaveCaptureInfo {
5990 -                       get { return capture_context != null; }
5991 -               }
5992 -
5993 -               public void EmitScopeInitFromBlock (Block b)
5994 -               {
5995 -                       if (capture_context != null)
5996 -                               capture_context.EmitScopeInitFromBlock (this, b);
5997 -               }
5998 -
5999                 // <summary>
6000                 //   Starts a new code branching.  This inherits the state of all local
6001                 //   variables and parameters from the current branching.
6002 @@ -618,84 +596,17 @@
6003                         current_flow_branching = current_flow_branching.Parent;
6004                 }
6005  
6006 -               public void CaptureVariable (LocalInfo li)
6007 +               public bool MustCaptureVariable (LocalInfo local)
6008                 {
6009 -                       capture_context.AddLocal (CurrentAnonymousMethod, li);
6010 -                       li.IsCaptured = true;
6011 +                       if (CurrentAnonymousMethod == null)
6012 +                               return false;
6013 +                       if (CurrentAnonymousMethod.IsIterator)
6014 +                               return true;
6015 +                       return local.Block.Toplevel != CurrentBlock.Toplevel;
6016                 }
6017 -
6018 -               public void CaptureParameter (string name, Type t, int idx)
6019 -               {
6020 -                       capture_context.AddParameter (this, CurrentAnonymousMethod, name, t, idx);
6021 -               }
6022 -
6023 -               public void CaptureThis ()
6024 -               {
6025 -                       capture_context.CaptureThis (CurrentAnonymousMethod);
6026 -               }
6027                 
6028 -               
6029 -               //
6030 -               // Use to register a field as captured
6031 -               //
6032 -               public void CaptureField (FieldExpr fe)
6033 -               {
6034 -                       capture_context.AddField (this, CurrentAnonymousMethod, fe);
6035 -               }
6036 -
6037 -               //
6038 -               // Whether anonymous methods have captured variables
6039 -               //
6040 -               public bool HaveCapturedVariables ()
6041 -               {
6042 -                       if (capture_context != null)
6043 -                               return capture_context.HaveCapturedVariables;
6044 -                       return false;
6045 -               }
6046 -
6047 -               //
6048 -               // Whether anonymous methods have captured fields or this.
6049 -               //
6050 -               public bool HaveCapturedFields ()
6051 -               {
6052 -                       if (capture_context != null)
6053 -                               return capture_context.HaveCapturedFields;
6054 -                       return false;
6055 -               }
6056 -
6057 -               //
6058 -               // Emits the instance pointer for the host method
6059 -               //
6060 -               public void EmitMethodHostInstance (EmitContext target, AnonymousMethod am)
6061 -               {
6062 -                       if (capture_context != null)
6063 -                               capture_context.EmitMethodHostInstance (target, am);
6064 -                       else if (IsStatic)
6065 -                               target.ig.Emit (OpCodes.Ldnull);
6066 -                       else
6067 -                               target.ig.Emit (OpCodes.Ldarg_0);
6068 -               }
6069 -
6070 -               //
6071 -               // Returns whether the `local' variable has been captured by an anonymous
6072 -               // method
6073 -               //
6074 -               public bool IsCaptured (LocalInfo local)
6075 -               {
6076 -                       return capture_context.IsCaptured (local);
6077 -               }
6078 -
6079 -               public bool IsParameterCaptured (string name)
6080 -               {
6081 -                       if (capture_context != null)
6082 -                               return capture_context.IsParameterCaptured (name);
6083 -                       return false;
6084 -               }
6085 -               
6086                 public void EmitMeta (ToplevelBlock b)
6087                 {
6088 -                       if (capture_context != null)
6089 -                               capture_context.EmitAnonymousHelperClasses (this);
6090                         b.EmitMeta (this);
6091  
6092                         if (HasReturnLabel)
6093 @@ -734,8 +645,6 @@
6094                         if (resolved)
6095                                 return true;
6096  
6097 -                       capture_context = block.CaptureContext;
6098 -
6099                         if (!loc.IsNull)
6100                                 CurrentFile = loc.File;
6101  
6102 @@ -745,6 +654,11 @@
6103                                 if (!block.ResolveMeta (this, ip))
6104                                         return false;
6105  
6106 +                               if ((md != null) && (md.Iterator != null)) {
6107 +                                       if (!md.Iterator.Resolve (this))
6108 +                                               throw new InternalErrorException ();
6109 +                               }
6110 +
6111                                 using (this.With (EmitContext.Flags.DoFlowAnalysis, true)) {
6112                                         FlowBranchingToplevel top_level;
6113                                         if (anonymous_method_host != null)
6114 @@ -783,12 +697,14 @@
6115                                         return false;
6116                                 } else if (!CurrentAnonymousMethod.IsIterator) {
6117                                         Report.Error (1643, CurrentAnonymousMethod.Location, "Not all code paths return a value in anonymous method of type `{0}'",
6118 -                                               CurrentAnonymousMethod.GetSignatureForError ());
6119 +                                                     CurrentAnonymousMethod.GetSignatureForError ());
6120                                         return false;
6121                                 }
6122                         }
6123  
6124 -                       block.CompleteContexts ();
6125 +                       if (!block.CompleteContexts (this))
6126 +                               return false;
6127 +
6128                         resolved = true;
6129                         return true;
6130                 }
6131 @@ -829,12 +745,6 @@
6132                                         ig.Emit (OpCodes.Ret);
6133                                 }
6134                         }
6135 -
6136 -                       //
6137 -                       // Close pending helper classes if we are the toplevel
6138 -                       //
6139 -                       if (capture_context != null && capture_context.ParentToplevel == null)
6140 -                               capture_context.CloseAnonymousHelperClasses ();
6141                 }
6142  
6143                 /// <summary>
6144 @@ -1002,50 +912,24 @@
6145                 public void EmitThis (bool need_address)
6146                 {
6147                         ig.Emit (OpCodes.Ldarg_0);
6148 -                       if (capture_context != null && CurrentAnonymousMethod != null){
6149 -                               ScopeInfo si = CurrentAnonymousMethod.Scope;
6150 -                               while (si != null){
6151 -                                       if (si.ParentLink != null)
6152 -                                               ig.Emit (OpCodes.Ldfld, si.ParentLink);
6153 -                                       if (si.THIS != null){
6154 -                                               if (need_address && TypeManager.IsValueType (si.THIS.FieldType))
6155 -                                                       ig.Emit (OpCodes.Ldflda, si.THIS);
6156 -                                               else
6157 -                                                       ig.Emit (OpCodes.Ldfld, si.THIS);
6158 -                                               break;
6159 -                                       }
6160 -                                       si = si.ParentScope;
6161 +                       if (CurrentAnonymousMethod == null)
6162 +                               return;
6163 +
6164 +                       AnonymousMethodHost host = CurrentAnonymousMethod.RootScope;
6165 +                       while (host != null) {
6166 +                               if (host.ParentLink != null)
6167 +                                       ig.Emit (OpCodes.Ldfld, host.ParentLink.FieldBuilder);
6168 +                               if (host.THIS != null) {
6169 +                                       if (need_address && TypeManager.IsValueType (host.THIS.MemberType))
6170 +                                               ig.Emit (OpCodes.Ldflda, host.THIS.FieldBuilder);
6171 +                                       else
6172 +                                               ig.Emit (OpCodes.Ldfld, host.THIS.FieldBuilder);
6173 +                                       break;
6174                                 }
6175 -                       } 
6176 +                               host = host.ParentHost;
6177 +                       }
6178                 }
6179  
6180 -               //
6181 -               // Emits the code necessary to load the instance required
6182 -               // to access the captured LocalInfo
6183 -               //
6184 -               public void EmitCapturedVariableInstance (LocalInfo li)
6185 -               {
6186 -                       if (capture_context == null)
6187 -                               throw new Exception ("Calling EmitCapturedContext when there is no capture_context");
6188 -                       
6189 -                       capture_context.EmitCapturedVariableInstance (this, li, CurrentAnonymousMethod);
6190 -               }
6191 -
6192 -               public void EmitParameter (string name, bool leave_copy, bool prepared, ref LocalTemporary temp)
6193 -               {
6194 -                       capture_context.EmitParameter (this, name, leave_copy, prepared, ref temp);
6195 -               }
6196 -
6197 -               public void EmitAssignParameter (string name, Expression source, bool leave_copy, bool prepare_for_load, ref LocalTemporary  temp)
6198 -               {
6199 -                       capture_context.EmitAssignParameter (this, name, source, leave_copy, prepare_for_load, ref temp);
6200 -               }
6201 -
6202 -               public void EmitAddressOfParameter (string name)
6203 -               {
6204 -                       capture_context.EmitAddressOfParameter (this, name);
6205 -               }
6206 -               
6207                 public Expression GetThis (Location loc)
6208                 {
6209                         This my_this;
6210 Index: statement.cs
6211 ===================================================================
6212 --- statement.cs        (revision 63019)
6213 +++ statement.cs        (working copy)
6214 @@ -962,23 +962,35 @@
6215                 }
6216         }
6217  
6218 +       public abstract class Variable
6219 +       {
6220 +               public abstract Type Type {
6221 +                       get;
6222 +               }
6223 +
6224 +               public abstract bool HasInstance {
6225 +                       get;
6226 +               }
6227 +
6228 +               public abstract bool NeedsTemporary {
6229 +                       get;
6230 +               }
6231 +
6232 +               public abstract void EmitInstance (EmitContext ec);
6233 +
6234 +               public abstract void Emit (EmitContext ec);
6235 +
6236 +               public abstract void EmitAssign (EmitContext ec);
6237 +
6238 +               public abstract void EmitAddressOf (EmitContext ec);
6239 +       }
6240 +
6241         //
6242         // The information about a user-perceived local variable
6243         //
6244         public class LocalInfo {
6245                 public Expression Type;
6246  
6247 -               //
6248 -               // Most of the time a variable will be stored in a LocalBuilder
6249 -               //
6250 -               // But sometimes, it will be stored in a field (variables that have been
6251 -               // hoisted by iterators or by anonymous methods).  The context of the field will
6252 -               // be stored in the EmitContext
6253 -               //
6254 -               //
6255 -               public LocalBuilder LocalBuilder;
6256 -               public FieldBuilder FieldBuilder;
6257 -
6258                 public Type VariableType;
6259                 public readonly string Name;
6260                 public readonly Location Location;
6261 @@ -986,6 +998,11 @@
6262  
6263                 public VariableInfo VariableInfo;
6264  
6265 +               Variable var;
6266 +               public Variable Variable {
6267 +                       get { return var; }
6268 +               }
6269 +
6270                 [Flags]
6271                 enum Flags : byte {
6272                         Used = 1,
6273 @@ -1022,18 +1039,27 @@
6274                         Location = l;
6275                 }
6276  
6277 -               public void DeclareLocal (ILGenerator ig)
6278 +               public void ResolveVariable (EmitContext ec)
6279                 {
6280 -                       if (Pinned) {
6281 -                               //
6282 -                               // This is needed to compile on both .NET 1.x and .NET 2.x
6283 -                               // the later introduced `DeclareLocal (Type t, bool pinned)'
6284 -                               //
6285 -                               LocalBuilder = TypeManager.DeclareLocalPinned (ig, VariableType);
6286 -                               return;
6287 +                       Block theblock = Block;
6288 +                       while (theblock.Implicit)
6289 +                               theblock = theblock.Parent;
6290 +                       if (theblock.ScopeInfo != null)
6291 +                               var = theblock.ScopeInfo.GetCapturedVariable (this);
6292 +
6293 +                       if (var == null) {
6294 +                               LocalBuilder builder;
6295 +                               if (Pinned)
6296 +                                       //
6297 +                                       // This is needed to compile on both .NET 1.x and .NET 2.x
6298 +                                       // the later introduced `DeclareLocal (Type t, bool pinned)'
6299 +                                       //
6300 +                                       builder = TypeManager.DeclareLocalPinned (ec.ig, VariableType);
6301 +                               else
6302 +                                       builder = ec.ig.DeclareLocal (VariableType);
6303 +
6304 +                               var = new LocalVariable (this, builder);
6305                         }
6306 -                       if (!IsThis && !IsConstant)
6307 -                               LocalBuilder = ig.DeclareLocal (VariableType);
6308                 }
6309  
6310                 public bool IsThisAssigned (EmitContext ec, Location loc)
6311 @@ -1185,6 +1211,50 @@
6312                                 flags = value ? (flags | Flags.IsThis) : (flags & ~Flags.IsThis);
6313                         }
6314                 }
6315 +
6316 +               protected class LocalVariable : Variable
6317 +               {
6318 +                       public readonly LocalInfo LocalInfo;
6319 +                       LocalBuilder builder;
6320 +
6321 +                       public LocalVariable (LocalInfo local, LocalBuilder builder)
6322 +                       {
6323 +                               this.LocalInfo = local;
6324 +                               this.builder = builder;
6325 +                       }
6326 +
6327 +                       public override Type Type {
6328 +                               get { return LocalInfo.VariableType; }
6329 +                       }
6330 +
6331 +                       public override bool HasInstance {
6332 +                               get { return false; }
6333 +                       }
6334 +
6335 +                       public override bool NeedsTemporary {
6336 +                               get { return false; }
6337 +                       }
6338 +
6339 +                       public override void EmitInstance (EmitContext ec)
6340 +                       {
6341 +                               // Do nothing.
6342 +                       }
6343 +
6344 +                       public override void Emit (EmitContext ec)
6345 +                       {
6346 +                               ec.ig.Emit (OpCodes.Ldloc, builder);
6347 +                       }
6348 +
6349 +                       public override void EmitAssign (EmitContext ec)
6350 +                       {
6351 +                               ec.ig.Emit (OpCodes.Stloc, builder);
6352 +                       }
6353 +
6354 +                       public override void EmitAddressOf (EmitContext ec)
6355 +                       {
6356 +                               ec.ig.Emit (OpCodes.Ldloca, builder);
6357 +                       }
6358 +               }
6359         }
6360                 
6361         /// <summary>
6362 @@ -1239,7 +1309,7 @@
6363                 //
6364                 // The statements in this block
6365                 //
6366 -               ArrayList statements;
6367 +               protected ArrayList statements;
6368                 int num_statements;
6369  
6370                 //
6371 @@ -1275,6 +1345,8 @@
6372                 //
6373                 Block switch_block;
6374  
6375 +               ExpressionStatement scope_init;
6376 +
6377                 protected static int id;
6378  
6379                 int this_id;
6380 @@ -1589,6 +1661,8 @@
6381  
6382                 public LocalInfo AddTemporaryVariable (TypeExpr te, Location loc)
6383                 {
6384 +                       Report.Debug (64, "ADD TEMPORARY", this, Toplevel, loc);
6385 +
6386                         if (temporary_variables == null)
6387                                 temporary_variables = new ArrayList ();
6388  
6389 @@ -1679,6 +1753,19 @@
6390                         }
6391                 }
6392  
6393 +               public ScopeInfo ScopeInfo;
6394 +
6395 +               public ScopeInfo CreateScopeInfo ()
6396 +               {
6397 +                       if (Implicit)
6398 +                               return Parent.CreateScopeInfo ();
6399 +
6400 +                       if (ScopeInfo == null)
6401 +                               ScopeInfo = new ScopeInfo (Toplevel.AnonymousMethodHost, this);
6402 +
6403 +                       return ScopeInfo;
6404 +               }
6405 +
6406                 /// <summary>
6407                 ///   Emits the variable declarations and labels.
6408                 /// </summary>
6409 @@ -1688,6 +1775,8 @@
6410                 /// </remarks>
6411                 public void ResolveMeta (ToplevelBlock toplevel, EmitContext ec, Parameters ip)
6412                 {
6413 +                       Report.Debug (64, "BLOCK RESOLVE META", this, Parent, toplevel);
6414 +
6415                         // If some parent block was unsafe, we remain unsafe even if this block
6416                         // isn't explicitly marked as such.
6417                         using (ec.With (EmitContext.Flags.InUnsafe, ec.InUnsafe | Unsafe)) {
6418 @@ -1791,39 +1880,23 @@
6419                 //
6420                 // Emits the local variable declarations for a block
6421                 //
6422 -               public void EmitMeta (EmitContext ec)
6423 +               public virtual void EmitMeta (EmitContext ec)
6424                 {
6425 -                       ILGenerator ig = ec.ig;
6426 -                       
6427 +                       Report.Debug (64, "BLOCK EMIT META", this, Toplevel, ScopeInfo, ec);
6428 +                       if (ScopeInfo != null) {
6429 +                               scope_init = ScopeInfo.GetScopeInitializer (ec);
6430 +                               Report.Debug (64, "BLOCK EMIT META #1", this, Toplevel, ScopeInfo,
6431 +                                             ec, scope_init);
6432 +                       }
6433 +
6434                         if (variables != null){
6435 -                               bool have_captured_vars = ec.HaveCapturedVariables ();
6436 -                               
6437 -                               foreach (DictionaryEntry de in variables){
6438 -                                       LocalInfo vi = (LocalInfo) de.Value;
6439 -
6440 -                                       if (have_captured_vars && ec.IsCaptured (vi))
6441 -                                               continue;
6442 -
6443 -                                       vi.DeclareLocal (ig);
6444 -                               }
6445 +                               foreach (LocalInfo vi in variables.Values)
6446 +                                       vi.ResolveVariable (ec);
6447                         }
6448  
6449                         if (temporary_variables != null) {
6450 -                               AnonymousContainer am = ec.CurrentAnonymousMethod;
6451 -                               TypeBuilder scope = null;
6452 -                               if ((am != null) && am.IsIterator) {
6453 -                                       scope = am.Scope.ScopeTypeBuilder;
6454 -                                       if (scope == null)
6455 -                                               throw new InternalErrorException ();
6456 -                               }
6457 -                               foreach (LocalInfo vi in temporary_variables) {
6458 -                                       if (scope != null) {
6459 -                                               if (vi.FieldBuilder == null)
6460 -                                                       vi.FieldBuilder = scope.DefineField (
6461 -                                                               vi.Name, vi.VariableType, FieldAttributes.Assembly);
6462 -                                       } else
6463 -                                               vi.LocalBuilder = ig.DeclareLocal (vi.VariableType);
6464 -                               }
6465 +                               foreach (LocalInfo vi in temporary_variables)
6466 +                                       vi.ResolveVariable (ec);
6467                         }
6468  
6469                         if (children != null){
6470 @@ -2031,15 +2104,19 @@
6471                                                 string name = (string) de.Key;
6472                                                 LocalInfo vi = (LocalInfo) de.Value;
6473  
6474 +#if FIXME
6475                                                 if (vi.LocalBuilder == null)
6476                                                         continue;
6477  
6478                                                 ec.DefineLocalVariable (name, vi.LocalBuilder);
6479 +#endif
6480                                         }
6481                                 }
6482                         }
6483                         ec.Mark (StartLocation, true);
6484 -                       ec.EmitScopeInitFromBlock (this);
6485 +                       Report.Debug (64, "BLOCK EMIT", this, Toplevel, ec, scope_init);
6486 +                       if (scope_init != null)
6487 +                               scope_init.EmitStatement (ec);
6488                         DoEmit (ec);
6489                         ec.Mark (EndLocation, true); 
6490  
6491 @@ -2083,13 +2160,11 @@
6492                 // Pointer to the host of this anonymous method, or null
6493                 // if we are the topmost block
6494                 //
6495 -               ToplevelBlock container;
6496 -               CaptureContext capture_context;
6497 +               GenericMethod generic;
6498 +               ToplevelBlock container, child;
6499                 FlowBranchingToplevel top_level_branching;
6500 +               AnonymousMethodHost anonymous_method_host;
6501  
6502 -               Hashtable capture_contexts;
6503 -               ArrayList children;
6504 -
6505                 public bool HasVarargs {
6506                         get { return (flags & Flags.HasVarargs) != 0; }
6507                         set { flags |= Flags.HasVarargs; }
6508 @@ -2103,39 +2178,37 @@
6509                         get { return parameters; }
6510                 }
6511  
6512 -               public void RegisterCaptureContext (CaptureContext cc)
6513 +               public bool CompleteContexts (EmitContext ec)
6514                 {
6515 -                       if (capture_contexts == null)
6516 -                               capture_contexts = new Hashtable ();
6517 -                       capture_contexts [cc] = cc;
6518 -               }
6519 +                       Report.Debug (64, "TOPLEVEL COMPLETE CONTEXTS", this,
6520 +                                     container, anonymous_method_host);
6521  
6522 -               public void CompleteContexts ()
6523 -               {
6524 -                       if (capture_contexts == null)
6525 -                               return;
6526 +                       if (anonymous_method_host != null)
6527 +                               anonymous_method_host.LinkScopes ();
6528  
6529 -                       foreach (CaptureContext cc in capture_contexts.Keys){
6530 -                               cc.LinkScopes ();
6531 +                       if ((container == null) && (anonymous_method_host != null)) {
6532 +                               Report.Debug (64, "TOPLEVEL COMPLETE CONTEXTS #1", this,
6533 +                                             anonymous_method_host);
6534 +
6535 +                               if (anonymous_method_host.DefineType () == null)
6536 +                                       return false;
6537 +                               if (!anonymous_method_host.ResolveType ())
6538 +                                       return false;
6539 +                               if (!anonymous_method_host.DefineMembers ())
6540 +                                       return false;
6541                         }
6542 +
6543 +                       return true;
6544                 }
6545  
6546 -               public CaptureContext ToplevelBlockCaptureContext {
6547 -                       get { return capture_context; }
6548 +               public GenericMethod GenericMethod {
6549 +                       get { return generic; }
6550                 }
6551  
6552                 public ToplevelBlock Container {
6553                         get { return container; }
6554                 }
6555  
6556 -               protected void AddChild (ToplevelBlock block)
6557 -               {
6558 -                       if (children == null)
6559 -                               children = new ArrayList ();
6560 -
6561 -                       children.Add (block);
6562 -               }
6563 -
6564                 //
6565                 // Parent is only used by anonymous blocks to link back to their
6566                 // parents
6567 @@ -2144,6 +2217,13 @@
6568                         this (container, (Flags) 0, parameters, start)
6569                 {
6570                 }
6571 +
6572 +               public ToplevelBlock (ToplevelBlock container, Parameters parameters, GenericMethod generic,
6573 +                                     Location start) :
6574 +                       this (container, parameters, start)
6575 +               {
6576 +                       this.generic = generic;
6577 +               }
6578                 
6579                 public ToplevelBlock (Parameters parameters, Location start) :
6580                         this (null, (Flags) 0, parameters, start)
6581 @@ -2160,25 +2240,69 @@
6582                 {
6583                         this.parameters = parameters == null ? Parameters.EmptyReadOnlyParameters : parameters;
6584                         this.container = container;
6585 -
6586 -                       if (container != null)
6587 -                               container.AddChild (this);
6588                 }
6589  
6590                 public ToplevelBlock (Location loc) : this (null, (Flags) 0, null, loc)
6591                 {
6592                 }
6593  
6594 -               public void SetHaveAnonymousMethods (Location loc, AnonymousContainer host)
6595 +               public AnonymousMethodHost CreateAnonymousMethodHost (TypeContainer host)
6596                 {
6597 -                       if (capture_context == null)
6598 -                               capture_context = new CaptureContext (this, loc, host);
6599 +                       if (anonymous_method_host != null)
6600 +                               return anonymous_method_host;
6601 +
6602 +                       if (container != null)
6603 +                               anonymous_method_host = new AnonymousMethodHost (
6604 +                                       this, container.anonymous_method_host, null, StartLocation);
6605 +                       else
6606 +                               anonymous_method_host = new AnonymousMethodHost (
6607 +                                       this, host, generic, StartLocation);
6608 +
6609 +                       ScopeInfo = anonymous_method_host;
6610 +                       return anonymous_method_host;
6611                 }
6612  
6613 -               public CaptureContext CaptureContext {
6614 -                       get { return capture_context; }
6615 +               public void CreateIteratorHost (AnonymousMethodHost root_scope)
6616 +               {
6617 +                       Report.Debug (64, "CREATE ITERATOR HOST", this, root_scope,
6618 +                                     container, anonymous_method_host);
6619 +
6620 +                       if ((container != null) || (anonymous_method_host != null))
6621 +                               throw new InternalErrorException ();
6622 +
6623 +                       ScopeInfo = anonymous_method_host = root_scope;
6624                 }
6625  
6626 +               public AnonymousMethodHost AnonymousMethodHost {
6627 +                       get {
6628 +                               if (anonymous_method_host != null)
6629 +                                       return anonymous_method_host;
6630 +                               else if (container != null)
6631 +                                       return container.AnonymousMethodHost;
6632 +                               else
6633 +                                       return null;
6634 +                       }
6635 +               }
6636 +
6637 +               public void EmitScopeInstance (EmitContext ec, ScopeInfo scope)
6638 +               {
6639 +                       AnonymousMethodHost root_scope = AnonymousMethodHost;
6640 +
6641 +                       root_scope.EmitScopeInstance (ec);
6642 +                       while (root_scope != scope.Host) {
6643 +                               ec.ig.Emit (OpCodes.Ldfld, root_scope.ParentLink.FieldBuilder);
6644 +                               root_scope = root_scope.ParentHost;
6645 +
6646 +                               if (root_scope == null)
6647 +                                       throw new InternalErrorException (
6648 +                                               "Never found scope {0} starting at block {1}",
6649 +                                               scope, ec.CurrentBlock.ID);
6650 +                       }
6651 +
6652 +                       if (scope != scope.Host)
6653 +                               ec.ig.Emit (OpCodes.Ldfld, scope.ScopeInstance.FieldBuilder);
6654 +               }
6655 +
6656                 public FlowBranchingToplevel TopLevelBranching {
6657                         get { return top_level_branching; }
6658                 }
6659 @@ -2192,15 +2316,12 @@
6660                 // null.  Later on, when resolving the iterator, we need to move the
6661                 // anonymous method into that iterator.
6662                 //
6663 -               public void ReParent (ToplevelBlock new_parent, AnonymousContainer new_host)
6664 +               public void ReParent (ToplevelBlock new_parent)
6665                 {
6666 -                       foreach (ToplevelBlock block in children) {
6667 -                               if (block.CaptureContext == null)
6668 -                                       continue;
6669 -
6670 -                               block.container = new_parent;
6671 -                               block.CaptureContext.ReParent (new_parent, new_host);
6672 -                       }
6673 +                       Report.Debug (64, "TOPLEVEL REPARENT", this, Parent, new_parent);
6674 +                       container = new_parent;
6675 +                       Parent = new_parent;
6676 +                       new_parent.child = this;
6677                 }
6678  
6679                 //
6680 @@ -2290,10 +2411,58 @@
6681  
6682                         ResolveMeta (this, ec, ip);
6683  
6684 +                       if (child != null)
6685 +                               child.ResolveMeta (this, ec, ip);
6686 +
6687                         top_level_branching = ec.StartFlowBranching (this);
6688  
6689                         return Report.Errors == errors;
6690                 }
6691 +
6692 +               public override void EmitMeta (EmitContext ec)
6693 +               {
6694 +                       base.EmitMeta (ec);
6695 +                       parameters.ResolveVariable (this);
6696 +               }
6697 +
6698 +               public void MakeIterator (Iterator iterator)
6699 +               {
6700 +                       Report.Debug (64, "TOPLEVEL MAKE ITERATOR", this, statements);
6701 +
6702 +                       Block block = new Block (this);
6703 +                       foreach (Statement stmt in statements)
6704 +                               block.AddStatement (stmt);
6705 +                       statements = new ArrayList ();
6706 +                       statements.Add (new MoveNextStatement (iterator, block));
6707 +               }
6708 +
6709 +               protected class MoveNextStatement : Statement {
6710 +                       Iterator iterator;
6711 +                       Block block;
6712 +
6713 +                       public MoveNextStatement (Iterator iterator, Block block)
6714 +                       {
6715 +                               this.iterator = iterator;
6716 +                               this.block = block;
6717 +                               this.loc = iterator.Location;
6718 +                       }
6719 +
6720 +                       public override bool Resolve (EmitContext ec)
6721 +                       {
6722 +                               return block.Resolve (ec);
6723 +                       }
6724 +
6725 +                       protected override void DoEmit (EmitContext ec)
6726 +                       {
6727 +                               iterator.EmitMoveNext (ec, block);
6728 +                       }
6729 +               }
6730 +
6731 +               public override string ToString ()
6732 +               {
6733 +                       return String.Format ("{0} ({1}:{2}{3})", GetType (), ID, StartLocation,
6734 +                                             anonymous_method_host);
6735 +               }
6736         }
6737         
6738         public class SwitchLabel {
6739 @@ -3299,7 +3468,7 @@
6740                         }
6741  
6742                         public abstract void Emit (EmitContext ec);
6743 -                       public abstract void EmitExit (ILGenerator ig);
6744 +                       public abstract void EmitExit (EmitContext ec);
6745                 }
6746  
6747                 class ExpressionEmitter : Emitter {
6748 @@ -3313,14 +3482,14 @@
6749                                 // Store pointer in pinned location
6750                                 //
6751                                 converted.Emit (ec);
6752 -                               ec.ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
6753 +                               vi.Variable.EmitAssign (ec);
6754                         }
6755  
6756 -                       public override void EmitExit (ILGenerator ig)
6757 +                       public override void EmitExit (EmitContext ec)
6758                         {
6759 -                               ig.Emit (OpCodes.Ldc_I4_0);
6760 -                               ig.Emit (OpCodes.Conv_U);
6761 -                               ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
6762 +                               ec.ig.Emit (OpCodes.Ldc_I4_0);
6763 +                               ec.ig.Emit (OpCodes.Conv_U);
6764 +                               vi.Variable.EmitAssign (ec);
6765                         }
6766                 }
6767  
6768 @@ -3350,13 +3519,13 @@
6769                                         return;
6770  
6771                                 converted.Emit (ec);
6772 -                               ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
6773 +                               vi.Variable.EmitAssign (ec);
6774                         }
6775  
6776 -                       public override void EmitExit(ILGenerator ig)
6777 +                       public override void EmitExit (EmitContext ec)
6778                         {
6779 -                               ig.Emit (OpCodes.Ldnull);
6780 -                               ig.Emit (OpCodes.Stloc, pinned_string);
6781 +                               ec.ig.Emit (OpCodes.Ldnull);
6782 +                               ec.ig.Emit (OpCodes.Stloc, pinned_string);
6783                         }
6784                 }
6785  
6786 @@ -3554,13 +3723,11 @@
6787                         if (has_ret)
6788                                 return;
6789  
6790 -                       ILGenerator ig = ec.ig;
6791 -
6792                         //
6793                         // Clear the pinned variable
6794                         //
6795                         for (int i = 0; i < data.Length; i++) {
6796 -                               data [i].EmitExit (ig);
6797 +                               data [i].EmitExit (ec);
6798                         }
6799                 }
6800         }
6801 @@ -3772,22 +3939,24 @@
6802                                 
6803                                 ig.BeginCatchBlock (c.CatchType);
6804  
6805 +#if FIXME
6806                                 if (c.VarBlock != null)
6807                                         ec.EmitScopeInitFromBlock (c.VarBlock);
6808 +#endif
6809                                 if (c.Name != null){
6810                                         vi = c.Block.GetLocalInfo (c.Name);
6811                                         if (vi == null)
6812                                                 throw new Exception ("Variable does not exist in this block");
6813  
6814 -                                       if (vi.IsCaptured){
6815 +                                       if (vi.Variable.NeedsTemporary) {
6816                                                 LocalBuilder e = ig.DeclareLocal (vi.VariableType);
6817                                                 ig.Emit (OpCodes.Stloc, e);
6818 -                                               
6819 -                                               ec.EmitCapturedVariableInstance (vi);
6820 +
6821 +                                               vi.Variable.EmitInstance (ec);
6822                                                 ig.Emit (OpCodes.Ldloc, e);
6823 -                                               ig.Emit (OpCodes.Stfld, vi.FieldBuilder);
6824 +                                               vi.Variable.EmitAssign (ec);
6825                                         } else
6826 -                                               ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
6827 +                                               vi.Variable.EmitAssign (ec);
6828                                 } else
6829                                         ig.Emit (OpCodes.Pop);
6830  
6831 @@ -4164,7 +4333,7 @@
6832  
6833                         Type var_type = texpr.Type;
6834  
6835 -                       if (expr.eclass == ExprClass.MethodGroup || expr is AnonymousMethod) {
6836 +                       if (expr.eclass == ExprClass.MethodGroup || expr is AnonymousMethodExpression) {
6837                                 Report.Error (446, expr.Location, "Foreach statement cannot operate on a `{0}'",
6838                                         expr.ExprClassName);
6839                                 return false;
6840 @@ -4220,7 +4389,7 @@
6841                         {
6842                                 EmitThis (ec);
6843                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
6844 -                               EmitStore (ec.ig);
6845 +                               EmitStore (ec);
6846                         }
6847  
6848                         public void Increment (EmitContext ec)
6849 @@ -4229,7 +4398,7 @@
6850                                 Emit (ec);
6851                                 ec.ig.Emit (OpCodes.Ldc_I4_1);
6852                                 ec.ig.Emit (OpCodes.Add);
6853 -                               EmitStore (ec.ig);
6854 +                               EmitStore (ec);
6855                         }
6856                 }
6857  
6858 @@ -4323,7 +4492,7 @@
6859  
6860                                         lengths [i].EmitThis (ec);
6861                                         ((ArrayAccess) access).EmitGetLength (ec, i);
6862 -                                       lengths [i].EmitStore (ig);
6863 +                                       lengths [i].EmitStore (ec);
6864                                 }
6865  
6866                                 for (int i = 0; i < rank; i++) {