f1326d8712d432113b7c2bfad5679cf80bcaa7d2
[mono.git] / mcs / mcs / anonymous.cs
1 //
2 // anonymous.cs: Support for anonymous methods
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximain.com)
6 //
7 // (C) 2003, 2004 Novell, Inc.
8 //
9 // TODO: Ideally, we should have the helper classes emited as a hierarchy to map
10 // their nesting, and have the visibility set to private, instead of NestedAssembly
11 //
12 //
13 //
14
15 using System;
16 using System.Text;
17 using System.Collections;
18 using System.Reflection;
19 using System.Reflection.Emit;
20
21 namespace Mono.CSharp {
22
23         public abstract class CompilerGeneratedClass : Class
24         {
25                 GenericMethod generic_method;
26                 static int next_index = 0;
27
28                 private static MemberName MakeProxyName (GenericMethod generic, Location loc)
29                 {
30                         string name = MakeName ("CompilerGenerated");
31                         if (generic != null) {
32                                 TypeArguments args = new TypeArguments (loc);
33                                 foreach (TypeParameter tparam in generic.CurrentTypeParameters)
34                                         args.Add (new SimpleName (tparam.Name, loc));
35                                 return new MemberName (name, args, loc);
36                         } else
37                                 return new MemberName (name, loc);
38                 }
39
40                 public static string MakeName (string prefix)
41                 {
42                         return "<>c__" + prefix + next_index++;
43                 }
44
45                 protected CompilerGeneratedClass (DeclSpace parent, GenericMethod generic,
46                                                   int mod, Location loc)
47                         : base (parent.NamespaceEntry, parent,
48                                 MakeProxyName (generic, loc), mod | Modifiers.COMPILER_GENERATED, null)
49                 {
50                         this.generic_method = generic;
51
52                         if (generic != null) {
53                                 ArrayList list = new ArrayList ();
54                                 foreach (TypeParameter tparam in generic.TypeParameters) {
55                                         if (tparam.Constraints != null)
56                                                 list.Add (tparam.Constraints.Clone ());
57                                 }
58                                 SetParameterInfo (list);
59                         }
60
61                         parent.PartialContainer.AddCompilerGeneratedClass (this);
62                 }
63
64                 protected override bool DefineNestedTypes ()
65                 {
66                         RootContext.RegisterCompilerGeneratedType (TypeBuilder);
67                         return base.DefineNestedTypes ();
68                 }
69
70                 protected override bool DoDefineMembers ()
71                 {
72                         members_defined = true;
73
74                         if (!base.DoDefineMembers ())
75                                 return false;
76
77                         if (CompilerGenerated != null) {
78                                 foreach (CompilerGeneratedClass c in CompilerGenerated) {
79                                         if (!c.DefineMembers ())
80                                                 throw new InternalErrorException ();
81                                 }
82                         }
83
84                         return true;
85                 }
86
87                 protected override bool DoResolveMembers ()
88                 {
89                         if (CompilerGenerated != null) {
90                                 foreach (CompilerGeneratedClass c in CompilerGenerated) {
91                                         if (!c.ResolveMembers ())
92                                                 return false;
93                                 }
94                         }
95
96                         return base.DoResolveMembers ();
97                 }
98
99                 public GenericMethod GenericMethod {
100                         get { return generic_method; }
101                 }
102
103                 public Parameters InflateParameters (Parameters ps)
104                 {
105                         if (generic_method == null)
106                                 return ps;
107
108                         int n = ps.Count;
109                         if (n == 0)
110                                 return ps;
111
112                         Parameter[] inflated_params = new Parameter [n];
113                         Type[] inflated_types = new Type [n];
114
115                         for (int i = 0; i < n; ++i) {
116                                 Parameter p = ps [i];
117                                 Type it = InflateType (p.ExternalType ()).ResolveAsTypeTerminal (this, false).Type;
118                                 inflated_types [i] = it;
119                                 inflated_params [i] = new Parameter (it, p.Name, p.ModFlags, p.OptAttributes, p.Location);
120                         }
121                         return new Parameters (inflated_params, inflated_types);
122                 }
123
124                 public TypeExpr InflateType (Type it)
125                 {
126 #if GMCS_SOURCE
127                         if (generic_method == null)
128                                 return new TypeExpression (it, Location);
129
130                         if (it.IsGenericParameter && (it.DeclaringMethod != null)) {
131                                 int pos = it.GenericParameterPosition;
132                                 it = CurrentTypeParameters [pos].Type;
133                         } else if (it.IsGenericType) {
134                                 Type[] args = it.GetGenericArguments ();
135
136                                 TypeArguments inflated = new TypeArguments (Location);
137                                 foreach (Type t in args)
138                                         inflated.Add (InflateType (t));
139
140                                 return new ConstructedType (it, inflated, Location);
141                         } else if (it.IsArray) {
142                                 TypeExpr et_expr = InflateType (it.GetElementType ());
143                                 int rank = it.GetArrayRank ();
144
145                                 Type et = et_expr.ResolveAsTypeTerminal (this, false).Type;
146                                 it = et.MakeArrayType (rank);
147                         }
148 #endif
149
150                         return new TypeExpression (it, Location);
151                 }
152
153                 public Field CaptureVariable (string name, TypeExpr type)
154                 {
155                         if (members_defined)
156                                 throw new InternalErrorException ("Helper class already defined!");
157                         if (type == null)
158                                 throw new ArgumentNullException ();
159
160                         return new CapturedVariableField (this, name, type);
161                 }
162
163                 bool members_defined;
164
165                 internal void CheckMembersDefined ()
166                 {
167                         if (members_defined)
168                                 throw new InternalErrorException ("Helper class already defined!");
169                 }
170
171                 protected class CapturedVariableField : Field
172                 {
173                         public CapturedVariableField (CompilerGeneratedClass helper, string name,
174                                                       TypeExpr type)
175                                 : base (helper, type, Modifiers.INTERNAL, name, null, helper.Location)
176                         {
177                                 helper.AddField (this);
178                         }
179                 }
180         }
181
182         public class ScopeInfo : CompilerGeneratedClass
183         {
184                 protected readonly RootScopeInfo RootScope;
185                 new public readonly DeclSpace Parent;
186                 public readonly int ID = ++next_id;
187                 public Block ScopeBlock;
188
189                 static int next_id;
190
191                 public static ScopeInfo CreateScope (Block block)
192                 {
193                         ToplevelBlock toplevel = block.Toplevel;
194                         AnonymousContainer ac = toplevel.AnonymousContainer;
195
196                         Report.Debug (128, "CREATE SCOPE", block, block.ScopeInfo, toplevel, ac);
197
198                         if (ac == null)
199                                 return new ScopeInfo (block, toplevel.RootScope.Parent,
200                                                       toplevel.RootScope.GenericMethod);
201
202                         Report.Debug (128, "CREATE SCOPE #1", ac, ac.Host, ac.Scope, ac.Block,
203                                       ac.Container, ac.ContainerAnonymousMethod,
204                                       ac.Location);
205
206                         Block b;
207                         ScopeInfo parent = null;
208
209                         for (b = ac.Block; b != null; b = b.Parent) {
210                                 if (b.ScopeInfo != null) {
211                                         parent = b.ScopeInfo;
212                                         break;
213                                 }
214                         }
215
216                         Report.Debug (128, "CREATE SCOPE #2", parent);
217
218                         ScopeInfo new_scope = new ScopeInfo (block, parent, null);
219
220                         Report.Debug (128, "CREATE SCOPE #3", new_scope);
221
222                         return new_scope;
223                 }
224
225                 private static int default_modflags (DeclSpace parent)
226                 {
227                         return parent is CompilerGeneratedClass ? Modifiers.PUBLIC : Modifiers.PRIVATE;
228                 }
229
230                 protected ScopeInfo (Block block, DeclSpace parent, GenericMethod generic)
231                         : base (parent, generic, default_modflags (parent), block.StartLocation)
232                 {
233                         Parent = parent;
234                         RootScope = block.Toplevel.RootScope;
235                         ScopeBlock = block;
236
237                         Report.Debug (128, "NEW SCOPE", this, block,
238                                       block.Parent, block.Toplevel);
239
240                         RootScope.AddScope (this);
241                 }
242
243                 protected ScopeInfo (ToplevelBlock toplevel, DeclSpace parent,
244                                      GenericMethod generic, Location loc)
245                         : base (parent, generic, default_modflags (parent), loc)
246                 {
247                         Parent = parent;
248                         RootScope = (RootScopeInfo) this;
249                         ScopeBlock = toplevel;
250
251                         Report.Debug (128, "NEW ROOT SCOPE", this, toplevel, loc);
252                 }
253
254                 protected ScopeInitializer scope_initializer;
255
256                 Hashtable locals = new Hashtable ();
257                 Hashtable captured_scopes = new Hashtable ();
258                 Hashtable captured_params;
259
260                 protected CapturedScope[] CapturedScopes {
261                         get {
262                                 CapturedScope[] list = new CapturedScope [captured_scopes.Count];
263                                 captured_scopes.Values.CopyTo (list, 0);
264                                 return list;
265                         }
266                 }
267
268                 protected CapturedVariable GetCapturedScope (ScopeInfo scope)
269                 {
270                         return (CapturedVariable) captured_scopes [scope];
271                 }
272
273                 protected void EmitScopeInstance (EmitContext ec)
274                 {
275                         if (scope_initializer == null) {
276                                 //
277                                 // This is needed if someone overwrites the Emit method
278                                 // of Statement and manually calls Block.Emit without
279                                 // this snippet first:
280                                 // 
281                                 //   ec.EmitScopeInitFromBlock (The_Block);
282                                 //   The_Block.Emit (ec);
283                                 // 
284                                 throw new InternalErrorException ();
285                         }
286
287                         scope_initializer.Emit (ec);
288                 }
289
290                 public ExpressionStatement GetScopeInitializer (EmitContext ec)
291                 {
292                         Report.Debug (128, "GET SCOPE INITIALIZER",
293                                       this, GetType (), scope_initializer, ScopeBlock);
294
295                         if (scope_initializer == null) {
296                                 scope_initializer = CreateScopeInitializer ();
297                                 if (scope_initializer.Resolve (ec) == null)
298                                         throw new InternalErrorException ();
299                         }
300
301                         return scope_initializer;
302                 }
303
304                 public Type GetScopeType (EmitContext ec)
305                 {
306                         if (!IsGeneric)
307                                 return TypeBuilder;
308
309                         TypeArguments targs = new TypeArguments (Location);
310
311                         if (ec.DeclContainer.Parent.IsGeneric)
312                                 foreach (TypeParameter t in ec.DeclContainer.Parent.TypeParameters)
313                                         targs.Add (new TypeParameterExpr (t, Location));
314                         if (ec.DeclContainer.IsGeneric)
315                                 foreach (TypeParameter t in ec.DeclContainer.CurrentTypeParameters)
316                                         targs.Add (new TypeParameterExpr (t, Location));
317
318                         Report.Debug (128, "GET SCOPE TYPE", this, TypeBuilder, targs,
319                                       ec.DeclContainer, ec.DeclContainer.GetType (),
320                                       ec.DeclContainer.Parent.Name);
321
322                         TypeExpr te = new ConstructedType (TypeBuilder, targs, Location);
323                         te = te.ResolveAsTypeTerminal (ec, false);
324                         if ((te == null) || (te.Type == null))
325                                 return null;
326                         return te.Type;
327                 }
328
329                 protected override bool DoDefineMembers ()
330                 {
331                         Report.Debug (64, "SCOPE INFO DEFINE MEMBERS", this, GetType (), IsGeneric,
332                                       Parent.IsGeneric, GenericMethod);
333
334                         foreach (CapturedScope child in CapturedScopes) {
335                                 if (!child.DefineMembers ())
336                                         return false;
337                         }
338
339                         return base.DoDefineMembers ();
340                 }
341
342                 protected override bool DoResolveMembers ()
343                 {
344                         Report.Debug (64, "SCOPE INFO RESOLVE MEMBERS", this, GetType (), IsGeneric,
345                                       Parent.IsGeneric, GenericMethod);
346
347                         return base.DoResolveMembers ();
348                 }
349
350                 public Variable CaptureScope (ScopeInfo child)
351                 {
352                         CheckMembersDefined ();
353                         Report.Debug (128, "CAPTURE SCOPE", this, GetType (), child, child.GetType ());
354                         if (child == this)
355                                 throw new InternalErrorException ();
356                         CapturedScope captured = (CapturedScope) captured_scopes [child];
357                         if (captured == null) {
358                                 captured = new CapturedScope (this, child);
359                                 captured_scopes.Add (child, captured);
360                         }
361                         return captured;
362                 }
363
364                 public Variable AddLocal (LocalInfo local)
365                 {
366                         Report.Debug (128, "CAPTURE LOCAL", this, local);
367                         Variable var = (Variable) locals [local];
368                         if (var == null) {
369                                 var = new CapturedLocal (this, local);
370                                 locals.Add (local, var);
371                                 local.IsCaptured = true;
372                         }
373                         return var;
374                 }
375
376                 public Variable GetCapturedVariable (LocalInfo local)
377                 {
378                         return (Variable) locals [local];
379                 }
380
381                 public bool HostsParameters {
382                         get { return captured_params != null; }
383                 }
384
385                 public Variable GetCapturedParameter (Parameter par)
386                 {
387                         if (captured_params != null)
388                                 return (Variable) captured_params [par];
389                         else
390                                 return null;
391                 }
392
393                 public bool IsParameterCaptured (string name)
394                 {                       
395                         if (captured_params != null)
396                                 return captured_params [name] != null;
397                         return false;
398                 }
399
400                 public Variable AddParameter (Parameter par, int idx)
401                 {
402                         if (captured_params == null)
403                                 captured_params = new Hashtable ();
404
405                         Variable var = (Variable) captured_params [par];
406                         if (var == null) {
407                                 var = new CapturedParameter (this, par, idx);
408                                 captured_params.Add (par, var);
409                                 par.IsCaptured = true;
410                         }
411
412                         return var;
413                 }
414
415                 protected string MakeFieldName (string local_name)
416                 {
417                         return "<" + ID + ":" + local_name + ">";
418                 }
419
420                 protected virtual ScopeInitializer CreateScopeInitializer ()
421                 {
422                         return new ScopeInitializer (this);
423                 }
424
425                 protected abstract class CapturedVariable : Variable
426                 {
427                         public readonly ScopeInfo Scope;
428                         public readonly string Name;
429
430                         public FieldExpr FieldInstance;
431                         protected Field field;
432
433                         protected CapturedVariable (ScopeInfo scope, string name)
434                         {
435                                 this.Scope = scope;
436                                 this.Name = name;
437                         }
438
439                         protected CapturedVariable (ScopeInfo scope, string name, Type type)
440                                 : this (scope, name)
441                         {
442                                 this.field = scope.CaptureVariable (
443                                         scope.MakeFieldName (name), scope.RootScope.InflateType (type));
444                         }
445
446                         public Field Field {
447                                 get { return field; }
448                         }
449
450                         public override Type Type {
451                                 get { return Field.MemberType; }
452                         }
453
454                         public override bool HasInstance {
455                                 get { return true; }
456                         }
457
458                         public override bool NeedsTemporary {
459                                 get { return true; }
460                         }
461
462                         protected FieldInfo GetField (EmitContext ec)
463                         {
464                                 if ((ec.CurrentBlock != null) &&
465                                     (ec.CurrentBlock.Toplevel != Scope.ScopeBlock.Toplevel))
466                                         return Field.FieldBuilder;
467                                 else
468                                         return FieldInstance.FieldInfo;
469                         }
470
471                         public override void EmitInstance (EmitContext ec)
472                         {
473                                 if ((ec.CurrentAnonymousMethod != null) &&
474                                     (ec.CurrentAnonymousMethod.Scope == Scope)) {
475                                         ec.ig.Emit (OpCodes.Ldarg_0);
476                                         return;
477                                 }
478
479                                 Scope.EmitScopeInstance (ec);
480                         }
481
482                         public override void Emit (EmitContext ec)
483                         {
484                                 ec.ig.Emit (OpCodes.Ldfld, GetField (ec));
485                         }
486
487                         public override void EmitAssign (EmitContext ec)
488                         {
489                                 ec.ig.Emit (OpCodes.Stfld, GetField (ec));
490                         }
491
492                         public override void EmitAddressOf (EmitContext ec)
493                         {
494                                 ec.ig.Emit (OpCodes.Ldflda, GetField (ec));
495                         }
496                 }
497
498                 protected class CapturedParameter : CapturedVariable {
499                         public readonly Parameter Parameter;
500                         public readonly int Idx;
501
502                         public CapturedParameter (ScopeInfo scope, Parameter par, int idx)
503                                 : base (scope, par.Name, par.ParameterType)
504                         {
505                                 this.Parameter = par;
506                                 this.Idx = idx;
507                         }
508
509                         public override string ToString ()
510                         {
511                                 return String.Format ("{0} ({1}:{2}:{3})", GetType (), Field,
512                                                       Parameter.Name, Idx);
513                         }
514                 }
515
516                 protected class CapturedLocal : CapturedVariable {
517                         public readonly LocalInfo Local;
518
519                         public CapturedLocal (ScopeInfo scope, LocalInfo local)
520                                 : base (scope, local.Name, local.VariableType)
521                         {
522                                 this.Local = local;
523                         }
524
525                         public override string ToString ()
526                         {
527                                 return String.Format ("{0} ({1}:{2})", GetType (), Field,
528                                                       Local.Name);
529                         }
530                 }
531
532                 protected class CapturedThis : CapturedVariable {
533                         public CapturedThis (RootScopeInfo host)
534                                 : base (host, "<>THIS", host.ParentType)
535                         { }
536                 }
537
538                 protected class CapturedScope : CapturedVariable {
539                         public readonly ScopeInfo ChildScope;
540
541                         public CapturedScope (ScopeInfo root, ScopeInfo child)
542                                 : base (root, "scope" + child.ID)
543                         {
544                                 this.ChildScope = child;
545                         }
546
547                         public bool DefineMembers ()
548                         {
549                                 Type type = ChildScope.IsGeneric ?
550                                         ChildScope.CurrentType : ChildScope.TypeBuilder;
551                                 Report.Debug (128, "CAPTURED SCOPE DEFINE MEMBERS", this, Scope,
552                                               ChildScope, Name, type);
553                                 if (type == null)
554                                         throw new InternalErrorException ();
555                                 field = Scope.CaptureVariable (
556                                         Scope.MakeFieldName (Name), Scope.InflateType (type));
557                                 return true;
558                         }
559
560                         public override string ToString ()
561                         {
562                                 return String.Format ("CapturedScope ({1} captured in {0})",
563                                                       Scope, ChildScope);
564                         }
565                 }
566
567                 static void DoPath (StringBuilder sb, ScopeInfo start)
568                 {
569                         sb.Append ((start.ID).ToString ());
570                 }
571                 
572                 public override string ToString ()
573                 {
574                         StringBuilder sb = new StringBuilder ();
575                         
576                         sb.Append ("{");
577                         DoPath (sb, this);
578                         sb.Append ("}");
579
580                         return sb.ToString ();
581                 }
582
583                 protected class ScopeInitializer : ExpressionStatement
584                 {
585                         ScopeInfo scope;
586                         CapturedVariable captured_scope;
587                         LocalBuilder scope_instance;
588                         ConstructorInfo scope_ctor;
589
590                         bool initialized;
591
592                         public ScopeInitializer (ScopeInfo scope)
593                         {
594                                 this.scope = scope;
595                                 this.loc = scope.Location;
596                                 eclass = ExprClass.Value;
597                         }
598
599                         public ScopeInfo Scope {
600                                 get { return scope; }
601                         }
602
603                         public override Expression DoResolve (EmitContext ec)
604                         {
605                                 if (scope_ctor != null)
606                                         return this;
607
608                                 Report.Debug (64, "RESOLVE SCOPE INITIALIZER BASE", this, Scope,
609                                               ec, ec.CurrentBlock);
610
611                                 type = Scope.GetScopeType (ec);
612                                 if (type == null)
613                                         throw new InternalErrorException ();
614
615                                 if (!DoResolveInternal (ec))
616                                         throw new InternalErrorException ();
617
618                                 return this;
619                         }
620
621                         protected virtual bool DoResolveInternal (EmitContext ec)
622                         {
623                                 MethodGroupExpr mg = (MethodGroupExpr) Expression.MemberLookupFinal (
624                                         ec, ec.ContainerType, type, ".ctor", MemberTypes.Constructor,
625                                         AllBindingFlags | BindingFlags.DeclaredOnly, loc);
626                                 if (mg == null)
627                                         throw new InternalErrorException ();
628
629                                 scope_ctor = (ConstructorInfo) mg.Methods [0];
630
631                                 Report.Debug (128, "RESOLVE THE INIT", this, Scope, Scope.RootScope,
632                                               Scope.RootScope.GetType ());
633
634                                 ScopeInfo host = Scope.RootScope;
635                                 if ((Scope != host) && (Scope.RootScope is IteratorHost)) {
636                                         captured_scope = host.GetCapturedScope (Scope);
637                                         Type root = host.GetScopeType (ec);
638                                         FieldExpr fe = (FieldExpr) Expression.MemberLookup (
639                                                 type, root, captured_scope.Field.Name, loc);
640                                         if (fe == null)
641                                                 throw new InternalErrorException ();
642
643                                         fe.InstanceExpression = this;
644                                         captured_scope.FieldInstance = fe;
645
646                                         Report.Debug (128, "RESOLVE THE INIT #1", this,
647                                                       captured_scope, fe);
648                                 } else
649                                         scope_instance = ec.ig.DeclareLocal (type);
650
651                                 foreach (CapturedLocal local in Scope.locals.Values) {
652                                         FieldExpr fe = (FieldExpr) Expression.MemberLookup (
653                                                 ec.ContainerType, type, local.Field.Name, loc);
654                                         Report.Debug (64, "RESOLVE SCOPE INITIALIZER #2", this, Scope,
655                                                       Scope, ec, ec.ContainerType, type,
656                                                       local.Field, local.Field.Name, loc, fe);
657                                         if (fe == null)
658                                                 throw new InternalErrorException ();
659
660                                         fe.InstanceExpression = this;
661                                         local.FieldInstance = fe;
662                                 }
663
664                                 if (Scope.HostsParameters) {
665                                         foreach (CapturedParameter cp in Scope.captured_params.Values) {
666                                                 FieldExpr fe = (FieldExpr) Expression.MemberLookup (
667                                                         ec.ContainerType, type, cp.Field.Name, loc);
668                                                 if (fe == null)
669                                                         throw new InternalErrorException ();
670
671                                                 fe.InstanceExpression = this;
672                                                 cp.FieldInstance = fe;
673                                         }
674                                 }
675
676                                 foreach (CapturedScope scope in Scope.CapturedScopes) {
677                                         FieldExpr fe = (FieldExpr) Expression.MemberLookup (
678                                                 ec.ContainerType, type, scope.Field.Name, loc);
679                                         Report.Debug (64, "RESOLVE SCOPE INITIALIZER #3", this, Scope,
680                                                       scope, ec, ec.ContainerType, type,
681                                                       scope.Field, scope.Field.Name, loc, fe);
682                                         if (fe == null)
683                                                 throw new InternalErrorException ();
684
685                                         fe.InstanceExpression = this;
686                                         scope.FieldInstance = fe;
687                                 }
688
689                                 return true;
690                         }
691
692                         protected virtual void EmitParameterReference (EmitContext ec,
693                                                                        CapturedParameter cp)
694                         {
695                                 int extra = ec.MethodIsStatic ? 0 : 1;
696                                 ParameterReference.EmitLdArg (ec.ig, cp.Idx + extra);
697                         }
698
699                         static int next_id;
700                         int id = ++next_id;
701
702                         protected virtual void DoEmit (EmitContext ec)
703                         {
704                                 if ((ec.CurrentBlock != null) &&
705                                     (ec.CurrentBlock.Toplevel != Scope.ScopeBlock.Toplevel)) {
706                                         ec.ig.Emit (OpCodes.Ldarg_0);
707
708                                         if (ec.CurrentAnonymousMethod != null) {
709                                                 ScopeInfo host = ec.CurrentAnonymousMethod.Scope;
710                                                 Variable captured = host.GetCapturedScope (scope);
711                                                 Report.Debug (128, "EMIT SCOPE INSTANCE #2",
712                                                               ec.CurrentAnonymousMethod, host,
713                                                               scope, captured);
714                                                 if (captured != null)
715                                                         captured.Emit (ec);
716                                         }
717                                 } else if (scope_instance != null)
718                                         ec.ig.Emit (OpCodes.Ldloc, scope_instance);
719                                 else {
720                                         Report.Debug (128, "DO EMIT", this, Scope, ec,
721                                                       scope_instance, captured_scope);
722                                         captured_scope.EmitInstance (ec);
723                                         captured_scope.Emit (ec);
724                                 }
725                         }
726
727                         protected void DoEmitInstance (EmitContext ec)
728                         {
729                                 Report.Debug (128, "DO EMIT INSTANCE", this, Scope, ec,
730                                               scope_instance, captured_scope);
731
732                                 if (scope_instance != null)
733                                         ec.ig.Emit (OpCodes.Ldloc, scope_instance);
734                                 else
735                                         captured_scope.EmitInstance (ec);
736                         }
737
738                         protected virtual void EmitScopeConstructor (EmitContext ec)
739                         {
740                                 ec.ig.Emit (OpCodes.Newobj, scope_ctor);
741                         }
742
743                         public override void Emit (EmitContext ec)
744                         {
745                                 if (!initialized)
746                                         throw new InternalErrorException (
747                                                 "Scope {0} not initialized yet", scope);
748
749                                 DoEmit (ec);
750                         }
751
752                         public override void EmitStatement (EmitContext ec)
753                         {
754                                 if (initialized)
755                                         return;
756
757                                 DoEmitStatement (ec);
758                                 initialized = true;
759                         }
760
761                         protected virtual void DoEmitStatement (EmitContext ec)
762                         {
763                                 Report.Debug (128, "EMIT SCOPE INITIALIZER STATEMENT", this, id,
764                                               Scope, scope_instance, ec);
765
766                                 ec.ig.Emit (OpCodes.Nop);
767                                 ec.ig.Emit (OpCodes.Ldc_I4, id);
768                                 ec.ig.Emit (OpCodes.Pop);
769                                 ec.ig.Emit (OpCodes.Nop);
770
771                                 if (scope_instance == null)
772                                         ec.ig.Emit (OpCodes.Ldarg_0);
773                                 EmitScopeConstructor (ec);
774                                 if (scope_instance != null)
775                                         ec.ig.Emit (OpCodes.Stloc, scope_instance);
776                                 else
777                                         captured_scope.EmitAssign (ec);
778
779                                 if (Scope.HostsParameters) {
780                                         foreach (CapturedParameter cp in Scope.captured_params.Values) {
781                                                 Report.Debug (128, "EMIT SCOPE INIT #6", this,
782                                                               ec, ec.IsStatic, Scope, cp, cp.Field.Name);
783                                                 DoEmitInstance (ec);
784                                                 EmitParameterReference (ec, cp);
785                                                 ec.ig.Emit (OpCodes.Stfld, cp.FieldInstance.FieldInfo);
786                                         }
787                                 }
788
789                                 if (Scope is IteratorHost)
790                                         return;
791
792                                 foreach (CapturedScope scope in Scope.CapturedScopes) {
793                                         ScopeInfo child = scope.ChildScope;
794
795                                         Report.Debug (128, "EMIT SCOPE INIT #5", this, Scope,
796                                                       scope.Scope, scope.ChildScope);
797
798                                         ExpressionStatement init = child.GetScopeInitializer (ec);
799                                         init.EmitStatement (ec);
800
801                                         DoEmit (ec);
802                                         scope.ChildScope.EmitScopeInstance (ec);
803                                         scope.EmitAssign (ec);
804                                 }
805                         }
806                 }
807         }
808
809         public class RootScopeInfo : ScopeInfo
810         {
811                 public RootScopeInfo (ToplevelBlock toplevel, DeclSpace parent,
812                                       GenericMethod generic, Location loc)
813                         : base (toplevel, parent, generic, loc)
814                 {
815                         scopes = new ArrayList ();
816                 }
817
818                 TypeExpr parent_type;
819                 CapturedVariableField parent_link;
820                 CapturedThis this_variable;
821                 protected ArrayList scopes;
822
823                 public virtual bool IsIterator {
824                         get { return false; }
825                 }
826
827                 public RootScopeInfo ParentHost {
828                         get { return Parent.PartialContainer as RootScopeInfo; }
829                 }
830
831                 public Type ParentType {
832                         get { return parent_type.Type; }
833                 }
834
835                 public Field ParentLink {
836                         get { return parent_link; }
837                 }
838
839                 protected CapturedThis THIS {
840                         get { return this_variable; }
841                 }
842
843                 public Variable CaptureThis ()
844                 {
845                         if (ParentHost != null)
846                                 return ParentHost.CaptureThis ();
847
848                         CheckMembersDefined ();
849                         if (this_variable == null)
850                                 this_variable = new CapturedThis (this);
851                         return this_variable;
852                 }
853
854                 public void AddScope (ScopeInfo scope)
855                 {
856                         scopes.Add (scope);
857                 }
858
859                 bool linked;
860                 public void LinkScopes ()
861                 {
862                         Report.Debug (128, "LINK SCOPES", this, linked, scopes);
863
864                         if (linked)
865                                 return;
866
867                         linked = true;
868                         if (ParentHost != null)
869                                 ParentHost.LinkScopes ();
870
871                         foreach (ScopeInfo si in scopes) {
872                                 if (!si.Define ())
873                                         throw new InternalErrorException ();
874                                 if (si.DefineType () == null)
875                                         throw new InternalErrorException ();
876                                 if (!si.ResolveType ())
877                                         throw new InternalErrorException ();
878                         }
879
880                         foreach (ScopeInfo si in scopes) {
881                                 if (!si.ResolveMembers ())
882                                         throw new InternalErrorException ();
883                                 if (!si.DefineMembers ())
884                                         throw new InternalErrorException ();
885                         }
886                 }
887
888                 protected override ScopeInitializer CreateScopeInitializer ()
889                 {
890                         return new RootScopeInitializer (this);
891                 }
892
893                 protected override bool DefineNestedTypes ()
894                 {
895                         if (Parent.IsGeneric) {
896                                 parent_type = new ConstructedType (
897                                         Parent.TypeBuilder, Parent.TypeParameters, Location);
898                                 parent_type = parent_type.ResolveAsTypeTerminal (this, false);
899                                 if ((parent_type == null) || (parent_type.Type == null))
900                                         return false;
901                         } else {
902                                 parent_type = new TypeExpression (Parent.TypeBuilder, Location);
903                         }
904
905                         CompilerGeneratedClass parent = Parent.PartialContainer as CompilerGeneratedClass;
906                         if (parent != null)
907                                 parent_link = new CapturedVariableField (this, "<>parent", parent_type);
908
909                         return base.DefineNestedTypes ();
910                 }
911
912                 protected override bool DoDefineMembers ()
913                 {
914                         ArrayList args = new ArrayList ();
915                         if (this is IteratorHost)
916                                 args.Add (new Parameter (
917                                         TypeManager.int32_type, "$PC", Parameter.Modifier.NONE,
918                                         null, Location));
919
920                         Field pfield;
921                         if (Parent is CompilerGeneratedClass)
922                                 pfield = parent_link;
923                         else
924                                 pfield = this_variable !=  null ? this_variable.Field : null;
925                         if (pfield != null)
926                                 args.Add (new Parameter (
927                                         pfield.MemberType, "parent", Parameter.Modifier.NONE,
928                                         null, Location));
929
930                         Parameter[] ctor_params = new Parameter [args.Count];
931                         args.CopyTo (ctor_params, 0);
932                         Constructor ctor = new Constructor (
933                                 this, MemberName.Name, Modifiers.PUBLIC,
934                                 new Parameters (ctor_params),
935                                 new GeneratedBaseInitializer (Location),
936                                 Location);
937                         AddConstructor (ctor);
938
939                         ctor.Block = new ToplevelBlock (null, Location);
940                         ctor.Block.AddStatement (new TheCtor (this));
941
942                         return base.DoDefineMembers ();
943                 }
944
945                 protected virtual void EmitScopeConstructor (EmitContext ec)
946                 {
947                         int pos = (this is IteratorHost) ? 2 : 1;
948
949                         Field pfield;
950                         if (Parent is CompilerGeneratedClass)
951                                 pfield = parent_link;
952                         else
953                                 pfield = this_variable !=  null ? this_variable.Field : null;
954
955                         if (pfield != null) {
956                                 ec.ig.Emit (OpCodes.Ldarg_0);
957                                 ec.ig.Emit (OpCodes.Ldarg, pos);
958                                 ec.ig.Emit (OpCodes.Stfld, pfield.FieldBuilder);
959                                 pos++;
960                         }
961                 }
962
963                 protected class TheCtor : Statement
964                 {
965                         RootScopeInfo host;
966
967                         public TheCtor (RootScopeInfo host)
968                         {
969                                 this.host = host;
970                         }
971
972                         public override bool Resolve (EmitContext ec)
973                         {
974                                 return true;
975                         }
976
977                         protected override void DoEmit (EmitContext ec)
978                         {
979                                 host.EmitScopeConstructor (ec);
980                         }
981                 }
982
983                 protected class RootScopeInitializer : ScopeInitializer
984                 {
985                         RootScopeInfo host;
986
987                         public RootScopeInitializer (RootScopeInfo host)
988                                 : base (host)
989                         {
990                                 this.host = host;
991                         }
992
993                         public RootScopeInfo Host {
994                                 get { return host; }
995                         }
996
997                         protected override bool DoResolveInternal (EmitContext ec)
998                         {
999                                 Report.Debug (64, "RESOLVE ANONYMOUS METHOD HOST INITIALIZER",
1000                                               this, Host, Host.ParentType, loc);
1001
1002                                 if (Host.THIS != null) {
1003                                         FieldExpr fe = (FieldExpr) Expression.MemberLookup (
1004                                                 ec.ContainerType, type, Host.THIS.Field.Name, loc);
1005                                         if (fe == null)
1006                                                 throw new InternalErrorException ();
1007
1008                                         fe.InstanceExpression = this;
1009                                         Host.THIS.FieldInstance = fe;
1010                                 }
1011
1012                                 return base.DoResolveInternal (ec);
1013                         }
1014
1015                         protected virtual bool IsGetEnumerator {
1016                                 get { return false; }
1017                         }
1018
1019                         protected override void EmitScopeConstructor (EmitContext ec)
1020                         {
1021                                 if (host.THIS != null) {
1022                                         ec.ig.Emit (OpCodes.Ldarg_0);
1023                                         if (IsGetEnumerator)
1024                                                 ec.ig.Emit (OpCodes.Ldfld, host.THIS.Field.FieldBuilder);
1025                                         else if (host.THIS.Type.IsValueType)
1026                                                 Expression.LoadFromPtr (ec.ig, host.THIS.Type);
1027                                 } else if (host.ParentLink != null)
1028                                         ec.ig.Emit (OpCodes.Ldarg_0);
1029
1030                                 base.EmitScopeConstructor (ec);
1031                         }
1032                 }
1033
1034         }
1035
1036         public interface IAnonymousContainer
1037         {
1038                 Block Container {
1039                         get;
1040                 }
1041
1042                 GenericMethod GenericMethod {
1043                         get;
1044                 }
1045
1046                 RootScopeInfo RootScope {
1047                         get;
1048                 }
1049
1050                 bool IsIterator {
1051                         get;
1052                 }
1053         }
1054
1055         public interface IAnonymousHost
1056         {
1057                 //
1058                 // Invoked if a yield statement is found in the body
1059                 //
1060                 void SetYields ();
1061
1062                 //
1063                 // Invoked if an anonymous method is found in the body
1064                 //
1065                 void AddAnonymousMethod (AnonymousMethodExpression anonymous);
1066         }
1067
1068         public class AnonymousMethodExpression : Expression, IAnonymousContainer, IAnonymousHost
1069         {
1070                 public readonly AnonymousMethodExpression Parent;
1071                 public readonly TypeContainer Host;
1072                 public Parameters Parameters;
1073
1074                 public ToplevelBlock Block;
1075                 protected AnonymousMethod anonymous;
1076
1077                 protected Block container;
1078                 protected readonly GenericMethod generic;
1079
1080                 public Block Container {
1081                         get { return container; }
1082                 }
1083
1084                 public GenericMethod GenericMethod {
1085                         get { return generic; }
1086                 }
1087
1088                 public AnonymousMethod AnonymousMethod {
1089                         get { return anonymous; }
1090                 }
1091
1092                 public RootScopeInfo RootScope {
1093                         get { return root_scope; }
1094                 }
1095
1096                 public AnonymousMethodExpression (AnonymousMethodExpression parent,
1097                                                   GenericMethod generic, TypeContainer host,
1098                                                   Parameters parameters, Block container,
1099                                                   Location loc)
1100                 {
1101                         this.Parent = parent;
1102                         this.generic = parent != null ? null : generic;
1103                         this.Host = host;
1104                         this.Parameters = parameters;
1105                         this.container = container;
1106                         this.loc = loc;
1107
1108                         Report.Debug (64, "NEW ANONYMOUS METHOD EXPRESSION", this, parent, host,
1109                                       container, loc);
1110
1111                         if (parent != null)
1112                                 parent.AddAnonymousMethod (this);
1113                 }
1114
1115                 ArrayList children;
1116                 RootScopeInfo root_scope;
1117
1118                 static int next_index;
1119
1120                 void IAnonymousHost.SetYields ()
1121                 {
1122                         throw new InvalidOperationException ();
1123                 }
1124
1125                 public void AddAnonymousMethod (AnonymousMethodExpression anonymous)
1126                 {
1127                         if (children == null)
1128                                 children = new ArrayList ();
1129                         children.Add (anonymous);
1130                 }
1131
1132                 public bool CreateAnonymousHelpers ()
1133                 {
1134                         Report.Debug (64, "ANONYMOUS METHOD EXPRESSION CREATE ROOT SCOPE",
1135                                       this, Host, container, loc);
1136
1137                         if (container != null)
1138                                 root_scope = container.Toplevel.CreateRootScope (Host);
1139
1140                         if (children != null) {
1141                                 foreach (AnonymousMethodExpression child in children) {
1142                                         if (!child.CreateAnonymousHelpers ())
1143                                                 return false;
1144                                 }
1145                         }
1146
1147                         return true;
1148                 }
1149
1150                 public override string ExprClassName {
1151                         get {
1152                                 return "anonymous method";
1153                         }
1154                 }
1155
1156                 void Error_ParameterMismatch (Type t)
1157                 {
1158                         Report.Error (1661, loc, "Anonymous method could not be converted to delegate `" +
1159                                       "{0}' since there is a parameter mismatch",
1160                                       TypeManager.CSharpName (t));
1161                 }
1162
1163                 public virtual bool ImplicitStandardConversionExists (Type delegate_type)
1164                 {
1165                         if (Parameters == null)
1166                                 return true;
1167
1168                         MethodGroupExpr invoke_mg = Delegate.GetInvokeMethod (
1169                                 Host.TypeBuilder, delegate_type, loc);
1170                         MethodInfo invoke_mb = (MethodInfo) invoke_mg.Methods [0];
1171                         ParameterData invoke_pd = TypeManager.GetParameterData (invoke_mb);
1172
1173                         if (Parameters.Count != invoke_pd.Count)
1174                                 return false;
1175
1176                         for (int i = 0; i < Parameters.Count; ++i) {
1177                                 if (invoke_pd.ParameterType (i) != Parameters.ParameterType (i))
1178                                         return false;
1179                         }
1180                         return true;
1181                 }
1182
1183                 protected Expression CompatibleChecks (EmitContext ec, Type delegate_type)
1184                 {
1185                         if (!ec.IsAnonymousMethodAllowed) {
1186                                 Report.Error (1706, loc,
1187                                               "Anonymous methods are not allowed in the " +
1188                                               "attribute declaration");
1189                                 return null;
1190                         }
1191                         
1192                         if (!TypeManager.IsDelegateType (delegate_type)){
1193                                 Report.Error (1660, loc,
1194                                               "Cannot convert anonymous method block to type " +
1195                                               "`{0}' because it is not a delegate type",
1196                                               TypeManager.CSharpName (delegate_type));
1197                                 return null;
1198                         }
1199                         return this;
1200                 }
1201
1202                 protected bool VerifyExplicitParameterCompatibility (Type delegate_type, ParameterData invoke_pd, bool showErrors)
1203                 {
1204                         if (Parameters.Count != invoke_pd.Count) {
1205                                 if (!showErrors)
1206                                         return false;
1207                                 
1208                                 Report.SymbolRelatedToPreviousError (delegate_type);
1209                                 Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments",
1210                                               TypeManager.CSharpName (delegate_type), Parameters.Count.ToString ());
1211                                 Error_ParameterMismatch (delegate_type);
1212                                 return false;
1213                         }
1214                         
1215                         for (int i = 0; i < Parameters.Count; ++i) {
1216                                 Parameter.Modifier p_mod = invoke_pd.ParameterModifier (i);
1217                                 if (Parameters.ParameterModifier (i) != p_mod && p_mod != Parameter.Modifier.PARAMS) {
1218                                         if (!showErrors)
1219                                                 return false;
1220                                         
1221                                         if (p_mod == Parameter.Modifier.NONE)
1222                                                 Report.Error (1677, loc, "Parameter `{0}' should not be declared with the `{1}' keyword",
1223                                                               (i + 1).ToString (), Parameter.GetModifierSignature (Parameters.ParameterModifier (i)));
1224                                         else
1225                                                 Report.Error (1676, loc, "Parameter `{0}' must be declared with the `{1}' keyword",
1226                                                               (i+1).ToString (), Parameter.GetModifierSignature (p_mod));
1227                                         Error_ParameterMismatch (delegate_type);
1228                                         return false;
1229                                 }
1230
1231                                 // We assume that generic parameters are always inflated
1232                                 if (TypeManager.IsGenericParameter (invoke_pd.Types[i]))
1233                                         continue;
1234                                 
1235                                 if (invoke_pd.ParameterType (i) != Parameters.ParameterType (i)) {
1236                                         if (!showErrors)
1237                                                 return false;
1238                                         
1239                                         Report.Error (1678, loc, "Parameter `{0}' is declared as type `{1}' but should be `{2}'",
1240                                                       (i+1).ToString (),
1241                                                       TypeManager.CSharpName (Parameters.ParameterType (i)),
1242                                                       TypeManager.CSharpName (invoke_pd.ParameterType (i)));
1243                                         Error_ParameterMismatch (delegate_type);
1244                                         return false;
1245                                 }
1246                         }
1247                         return true;
1248                 }
1249
1250 #if GMCS_SOURCE         
1251                 // TODO: Merge with lambda DoCompatibleTest
1252                 // TODO: Need to sort out error reporting
1253                 public Expression InferTypeArguments (EmitContext ec, Type delegateType)
1254                 {
1255                         if (anonymous != null)
1256                                 return anonymous.AnonymousDelegate;
1257
1258                         if (!delegateType.ContainsGenericParameters)
1259                                 throw new InternalErrorException ("No inference required");
1260
1261                         // It looks like we cannot generate arguments during type inference
1262                         if (Parameters == null)
1263                                 return null;
1264
1265                         delegateType = delegateType.GetGenericTypeDefinition ();
1266                         
1267                         MethodGroupExpr invoke_mg = Delegate.GetInvokeMethod (
1268                                 ec.ContainerType, delegateType, loc);
1269                         MethodInfo invoke_mb = (MethodInfo) invoke_mg.Methods [0];
1270                         ParameterData invoke_pd = TypeManager.GetParameterData (invoke_mb);                     
1271
1272                         if (!VerifyExplicitParameterCompatibility (delegateType, invoke_pd, false))
1273                                 return null;
1274
1275                         Type[] g_arguments = delegateType.GetGenericArguments ();
1276                         Type[] inferred_arguments = new Type [g_arguments.Length];
1277                         g_arguments.CopyTo (inferred_arguments, 0);
1278
1279                         for (int i = 0; i < invoke_pd.Count; ++i) {
1280                                 if (!invoke_pd.Types[i].IsGenericParameter)
1281                                         continue;
1282
1283                                 inferred_arguments [invoke_pd.Types[i].GenericParameterPosition] = Parameters.Types[i];
1284                         }
1285
1286                         int return_type_pos = -1;
1287                         if (TypeManager.IsGenericParameter (invoke_mb.ReturnType)) {
1288                                         ec.InferReturnType = true;
1289                                 return_type_pos = invoke_mb.ReturnType.GenericParameterPosition;
1290                         }
1291
1292                         anonymous = new AnonymousMethod (
1293                                 Parent != null ? Parent.AnonymousMethod : null, RootScope, Host,
1294                                 GenericMethod, Parameters, Container, Block, invoke_mb.ReturnType,
1295                                 delegateType, loc);
1296
1297                         if (!anonymous.Resolve (ec))
1298                                 return null;
1299
1300                         if (return_type_pos != -1) {
1301                                 inferred_arguments [return_type_pos] = anonymous.ReturnType;
1302                         }
1303
1304                         anonymous.AnonymousDelegate.Type = delegateType.GetGenericTypeDefinition ().MakeGenericType (inferred_arguments);
1305                         anonymous.DelegateType = anonymous.AnonymousDelegate.Type;
1306                         
1307                         return anonymous.AnonymousDelegate;
1308                 }
1309 #endif
1310                 
1311                 //
1312                 // Returns true if this anonymous method can be implicitly
1313                 // converted to the delegate type `delegate_type'
1314                 //
1315                 public virtual Expression Compatible (EmitContext ec, Type delegate_type)
1316                 {
1317                         if (anonymous != null)
1318                                 return anonymous.AnonymousDelegate;
1319                         
1320                         if (CompatibleChecks (ec, delegate_type) == null)
1321                                 return null;
1322
1323                         //
1324                         // At this point its the first time we know the return type that is 
1325                         // needed for the anonymous method.  We create the method here.
1326                         //
1327
1328                         MethodGroupExpr invoke_mg = Delegate.GetInvokeMethod (
1329                                 ec.ContainerType, delegate_type, loc);
1330                         MethodInfo invoke_mb = (MethodInfo) invoke_mg.Methods [0];
1331                         ParameterData invoke_pd = TypeManager.GetParameterData (invoke_mb);
1332
1333                         Parameters parameters;
1334                         if (Parameters == null) {
1335                                 //
1336                                 // We provide a set of inaccessible parameters
1337                                 //
1338                                 Parameter [] fixedpars = new Parameter [invoke_pd.Count];
1339                                                                 
1340                                 for (int i = 0; i < invoke_pd.Count; i++) {
1341                                         Parameter.Modifier i_mod = invoke_pd.ParameterModifier (i);
1342                                         if ((i_mod & Parameter.Modifier.OUTMASK) != 0) {
1343                                                 Report.Error (1688, loc, "Cannot convert anonymous " +
1344                                                               "method block without a parameter list " +
1345                                                               "to delegate type `{0}' because it has " +
1346                                                               "one or more `out' parameters.",
1347                                                               TypeManager.CSharpName (delegate_type));
1348                                                 return null;
1349                                         }
1350                                         fixedpars [i] = new Parameter (
1351                                                 invoke_pd.ParameterType (i), "+" + (++next_index),
1352                                                 invoke_pd.ParameterModifier (i), null, loc);
1353                                 }
1354                                                                 
1355                                 parameters = new Parameters (fixedpars);
1356                                 if (!parameters.Resolve (ec))
1357                                         return null;
1358                         } else {
1359                                 if (!VerifyExplicitParameterCompatibility (delegate_type, invoke_pd, true))
1360                                         return null;
1361
1362                                 parameters = Parameters;
1363                         }
1364
1365                         //
1366                         // Second: the return type of the delegate must be compatible with 
1367                         // the anonymous type.   Instead of doing a pass to examine the block
1368                         // we satisfy the rule by setting the return type on the EmitContext
1369                         // to be the delegate type return type.
1370                         //
1371
1372                         //MethodBuilder builder = method_data.MethodBuilder;
1373                         //ILGenerator ig = builder.GetILGenerator ();
1374
1375                         Report.Debug (64, "COMPATIBLE", this, Parent, GenericMethod, Host,
1376                                       Container, Block, invoke_mb.ReturnType, delegate_type,
1377                                       TypeManager.IsGenericType (delegate_type), loc);
1378
1379                         anonymous = new AnonymousMethod (
1380                                 Parent != null ? Parent.AnonymousMethod : null, RootScope, Host,
1381                                 GenericMethod, parameters, Container, Block, invoke_mb.ReturnType,
1382                                 delegate_type, loc);
1383
1384                         if (!anonymous.Resolve (ec))
1385                                 return null;
1386
1387                         return anonymous.AnonymousDelegate;
1388                 }
1389
1390                 public override Expression DoResolve (EmitContext ec)
1391                 {
1392                         //
1393                         // Set class type, set type
1394                         //
1395
1396                         eclass = ExprClass.Value;
1397
1398                         //
1399                         // This hack means `The type is not accessible
1400                         // anywhere', we depend on special conversion
1401                         // rules.
1402                         // 
1403                         type = TypeManager.anonymous_method_type;
1404
1405                         if ((Parameters != null) && !Parameters.Resolve (ec))
1406                                 return null;
1407
1408                         return this;
1409                 }
1410
1411                 public override void Emit (EmitContext ec)
1412                 {
1413                         // nothing, as we only exist to not do anything.
1414                 }
1415
1416                 public bool IsIterator {
1417                         get { return false; }
1418                 }
1419
1420                 protected override void CloneTo (CloneContext clonectx, Expression t)
1421                 {
1422                         AnonymousMethodExpression target = (AnonymousMethodExpression) t;
1423
1424                         target.Block = (ToplevelBlock) clonectx.LookupBlock (Block);
1425                         target.container = clonectx.LookupBlock (Block);
1426                         target.Parameters = Parameters.Clone ();
1427                 }
1428         }
1429
1430         public abstract class AnonymousContainer : IAnonymousContainer
1431         {
1432                 public readonly Location Location;
1433
1434                 public Parameters Parameters;
1435
1436                 //
1437                 // The block that makes up the body for the anonymous mehtod
1438                 //
1439                 public readonly ToplevelBlock Block;
1440
1441                 public readonly int ModFlags;
1442                 public Type ReturnType;
1443                 public readonly DeclSpace Host;
1444
1445                 //
1446                 // The implicit method we create
1447                 //
1448                 protected Method method;
1449                 protected EmitContext aec;
1450
1451                 // The emit context for the anonymous method
1452                 protected bool unreachable;
1453                 protected readonly Block container;
1454                 protected readonly GenericMethod generic;
1455
1456                 //
1457                 // Points to our container anonymous method if its present
1458                 //
1459                 public readonly AnonymousContainer ContainerAnonymousMethod;
1460
1461                 protected AnonymousContainer (AnonymousContainer parent, DeclSpace host,
1462                                               GenericMethod generic, Parameters parameters,
1463                                               Block container, ToplevelBlock block,
1464                                               Type return_type, int mod, Location loc)
1465                 {
1466                         this.ContainerAnonymousMethod = parent;
1467                         this.ReturnType = return_type;
1468                         this.ModFlags = mod | Modifiers.COMPILER_GENERATED;
1469                         this.Host = host;
1470
1471                         this.container = container;
1472                         this.generic = parent != null ? null : generic;
1473                         this.Parameters = parameters;
1474                         this.Block = block;
1475                         this.Location = loc;
1476
1477                         block.AnonymousContainer = this;
1478                 }
1479
1480                 public Method Method {
1481                         get { return method; }
1482                 }
1483
1484                 public abstract RootScopeInfo RootScope {
1485                         get;
1486                 }
1487
1488                 public abstract ScopeInfo Scope {
1489                         get;
1490                 }
1491
1492                 public abstract string GetSignatureForError ();
1493
1494                 public virtual bool ResolveNoDefine (EmitContext ec)
1495                 {
1496                         Report.Debug (64, "RESOLVE ANONYMOUS METHOD", this, Location, ec,
1497                                       RootScope, Parameters, ec.IsStatic);
1498
1499                         if (ReturnType != null) {
1500                                 TypeExpr return_type_expr;
1501                                 if (RootScope != null)
1502                                         return_type_expr = RootScope.InflateType (ReturnType);
1503                                 else
1504                                         return_type_expr = new TypeExpression (ReturnType, Location);
1505                                 return_type_expr = return_type_expr.ResolveAsTypeTerminal (ec, false);
1506                                 if ((return_type_expr == null) || (return_type_expr.Type == null))
1507                                         return false;
1508                                 ReturnType = return_type_expr.Type;
1509                         }
1510
1511                         if (RootScope != null)
1512                                 Parameters = RootScope.InflateParameters (Parameters);
1513
1514                         aec = new EmitContext (
1515                                 ec.ResolveContext, ec.TypeContainer,
1516                                 RootScope != null ? RootScope : Host, Location, null, ReturnType,
1517                                 /* REVIEW */ (ec.InIterator ? Modifiers.METHOD_YIELDS : 0) |
1518                                 (ec.InUnsafe ? Modifiers.UNSAFE : 0), /* No constructor */ false);
1519
1520                         aec.CurrentAnonymousMethod = this;
1521                         aec.IsFieldInitializer = ec.IsFieldInitializer;
1522                         aec.IsStatic = ec.IsStatic;
1523                         aec.InferReturnType = ec.InferReturnType;
1524
1525                         Report.Debug (64, "RESOLVE ANONYMOUS METHOD #1", this, Location, ec, aec,
1526                                       RootScope, Parameters, Block);
1527
1528                         bool unreachable;
1529                         if (!aec.ResolveTopBlock (ec, Block, Parameters, null, out unreachable))
1530                                 return false;
1531
1532                         return true;
1533                 }
1534
1535                 public virtual bool Resolve (EmitContext ec)
1536                 {
1537                         if (!ResolveNoDefine (ec))
1538                                 return false;
1539                         
1540                         Report.Debug (64, "RESOLVE ANONYMOUS METHOD #3", this, ec, aec, Block);
1541
1542                         if (aec.InferReturnType)
1543                                 ReturnType = aec.ReturnType;
1544
1545                         method = DoCreateMethodHost (ec);
1546
1547                         if (Scope != null)
1548                                 return true;
1549
1550                         if (!method.ResolveMembers ())
1551                                 return false;
1552                         return method.Define ();
1553                 }
1554
1555                 protected abstract Method DoCreateMethodHost (EmitContext ec);
1556
1557                 public Block Container {
1558                         get { return container; }
1559                 }
1560
1561                 public GenericMethod GenericMethod {
1562                         get { return generic; }
1563                 }
1564
1565                 public abstract bool IsIterator {
1566                         get;
1567                 }
1568
1569                 protected class AnonymousMethodMethod : Method
1570                 {
1571                         public readonly AnonymousContainer AnonymousMethod;
1572                         public readonly ScopeInfo Scope;
1573
1574                         public AnonymousMethodMethod (AnonymousContainer am, ScopeInfo scope,
1575                                                       GenericMethod generic, TypeExpr return_type,
1576                                                       int mod, MemberName name, Parameters parameters)
1577                                 : base (scope != null ? scope : am.Host,
1578                                         generic, return_type, mod | Modifiers.COMPILER_GENERATED, false, name, parameters, null)
1579                         {
1580                                 this.AnonymousMethod = am;
1581                                 this.Scope = scope;
1582
1583                                 if (scope != null) {
1584                                         scope.CheckMembersDefined ();
1585                                         scope.AddMethod (this);
1586                                 } else {
1587                                         ModFlags |= Modifiers.STATIC;
1588                                         am.Host.PartialContainer.AddMethod (this);
1589                                 }
1590                                 Block = am.Block;
1591                         }
1592
1593                         public override EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
1594                         {
1595                                 EmitContext aec = AnonymousMethod.aec;
1596                                 aec.ig = ig;
1597                                 aec.MethodIsStatic = Scope == null;
1598                                 return aec;
1599                         }
1600                 }
1601         }
1602
1603         public class AnonymousMethod : AnonymousContainer
1604         {
1605                 public Type DelegateType;
1606
1607                 //
1608                 // The value return by the Compatible call, this ensure that
1609                 // the code works even if invoked more than once (Resolve called
1610                 // more than once, due to the way Convert.ImplicitConversion works
1611                 //
1612                 Expression anonymous_delegate;
1613                 RootScopeInfo root_scope;
1614                 ScopeInfo scope;
1615
1616                 public AnonymousMethod (AnonymousMethod parent, RootScopeInfo root_scope,
1617                                         DeclSpace host, GenericMethod generic,
1618                                         Parameters parameters, Block container,
1619                                         ToplevelBlock block, Type return_type, Type delegate_type,
1620                                         Location loc)
1621                         : base (parent, host, generic, parameters, container, block,
1622                                 return_type, 0, loc)
1623                 {
1624                         this.DelegateType = delegate_type;
1625                         this.root_scope = root_scope;
1626                 }
1627
1628                 public override RootScopeInfo RootScope {
1629                         get { return root_scope; }
1630                 }
1631
1632                 public override ScopeInfo Scope {
1633                         get { return scope; }
1634                 }
1635
1636                 public override bool IsIterator {
1637                         get { return false; }
1638                 }
1639
1640                 public Expression AnonymousDelegate {
1641                         get { return anonymous_delegate; }
1642                 }
1643
1644                 public override string GetSignatureForError ()
1645                 {
1646                         return TypeManager.CSharpName (DelegateType);
1647                 }
1648
1649                 //
1650                 // Creates the host for the anonymous method
1651                 //
1652                 protected override Method DoCreateMethodHost (EmitContext ec)
1653                 {
1654                         string name = CompilerGeneratedClass.MakeName ("AnonymousMethod");
1655                         MemberName member_name;
1656
1657                         Report.Debug (128, "CREATE METHOD HOST #0", RootScope);
1658
1659                         Block b;
1660                         scope = RootScope;
1661
1662                         Report.Debug (128, "CREATE METHOD HOST #1", this, Block, Block.ScopeInfo,
1663                                       RootScope, Location);
1664
1665                         for (b = Block.Parent; b != null; b = b.Parent) {
1666                                 Report.Debug (128, "CREATE METHOD HOST #2", this, Block,
1667                                               b, b.ScopeInfo);
1668                                 if (b.ScopeInfo != null) {
1669                                         scope = b.ScopeInfo;
1670                                         break;
1671                                 }
1672                         }
1673
1674                         if (scope != null)
1675                                 scope.CheckMembersDefined ();
1676
1677                         ArrayList scopes = new ArrayList ();
1678                         if (b != null) {
1679                                 for (b = b.Parent; b != null; b = b.Parent) {
1680                                         if (b.ScopeInfo != null)
1681                                                 scopes.Add (b.ScopeInfo);
1682                                 }
1683                         }
1684
1685                         Report.Debug (128, "CREATE METHOD HOST #1", this, scope, scopes);
1686
1687                         foreach (ScopeInfo si in scopes)
1688                                 scope.CaptureScope (si);
1689
1690                         Report.Debug (128, "CREATE METHOD HOST", this, Block, container,
1691                                       RootScope, scope, scopes, Location,
1692                                       ContainerAnonymousMethod);
1693
1694                         GenericMethod generic_method = null;
1695 #if GMCS_SOURCE
1696                         if (TypeManager.IsGenericType (DelegateType)) {
1697                                 TypeArguments args = new TypeArguments (Location);
1698
1699                                 Type dt = DelegateType.GetGenericTypeDefinition ();
1700
1701                                 Type[] tparam = TypeManager.GetTypeArguments (dt);
1702                                 for (int i = 0; i < tparam.Length; i++)
1703                                         args.Add (new SimpleName (tparam [i].Name, Location));
1704
1705                                 member_name = new MemberName (name, args, Location);
1706
1707                                 Report.Debug (128, "CREATE METHOD HOST #5", this, DelegateType,
1708                                               TypeManager.GetTypeArguments (DelegateType),
1709                                               dt, tparam, args);
1710
1711                                 generic_method = new GenericMethod (
1712                                         Host.NamespaceEntry, scope, member_name,
1713                                         new TypeExpression (ReturnType, Location), Parameters);
1714
1715                                 generic_method.SetParameterInfo (null);
1716                         } else
1717 #endif
1718                                 member_name = new MemberName (name, Location);
1719
1720                         return new AnonymousMethodMethod (
1721                                 this, scope, generic_method, new TypeExpression (ReturnType, Location),
1722                                 Modifiers.INTERNAL, member_name, Parameters);
1723                 }
1724
1725                 bool ResolveAnonymousDelegate (EmitContext ec)
1726                 {
1727                         // If we are inferring the return type, set it to the discovered value.
1728                         if (DelegateType == null){
1729                                 DelegateType = aec.ReturnType;
1730                                 
1731                                 // The special value pointing to our internal type means it failed.
1732                                 if (DelegateType == typeof (AnonymousDelegate))
1733                                         return false;
1734                         }
1735
1736                         anonymous_delegate = new AnonymousDelegate (
1737                                 this, DelegateType, Location).Resolve (ec);
1738                         if (anonymous_delegate == null)
1739                                 return false;
1740                         return true;
1741                 }
1742
1743                 public override bool Resolve (EmitContext ec)
1744                 {
1745                         if (!base.Resolve (ec))
1746                                 return false;
1747
1748                         return ResolveAnonymousDelegate (ec);
1749                 }
1750
1751                 public override bool ResolveNoDefine (EmitContext ec)
1752                 {
1753                         if (!base.ResolveNoDefine (ec))
1754                                 return false;
1755
1756                         return ResolveAnonymousDelegate (ec);
1757                 }
1758
1759                 public MethodInfo GetMethodBuilder (EmitContext ec)
1760                 {
1761                         MethodInfo builder = method.MethodBuilder;
1762                         if ((Scope != null) && Scope.IsGeneric) {
1763                                 Type scope_type = Scope.GetScopeType (ec);
1764                                 if (scope_type == null)
1765                                         throw new InternalErrorException ();
1766
1767                                 MethodGroupExpr mg = (MethodGroupExpr) Expression.MemberLookup (
1768                                         ec.ContainerType, scope_type, builder.Name, Location);
1769
1770                                 if (mg == null)
1771                                         throw new InternalErrorException ();
1772                                 builder = (MethodInfo) mg.Methods [0];
1773                         }
1774
1775 #if GMCS_SOURCE
1776                         if (!DelegateType.IsGenericType)
1777                                 return builder;
1778
1779                         Type[] targs = TypeManager.GetTypeArguments (DelegateType);
1780                         return builder.MakeGenericMethod (targs);
1781 #else
1782                         return builder;
1783 #endif
1784                 }
1785
1786                 public static void Error_AddressOfCapturedVar (string name, Location loc)
1787                 {
1788                         Report.Error (1686, loc,
1789                                       "Local variable `{0}' or its members cannot have their " +
1790                                       "address taken and be used inside an anonymous method block",
1791                                       name);
1792                 }
1793         }
1794
1795         //
1796         // This will emit the code for the delegate, as well delegate creation on the host
1797         //
1798         public class AnonymousDelegate : DelegateCreation {
1799                 AnonymousMethod am;
1800
1801                 //
1802                 // if target_type is null, this means that we do not know the type
1803                 // for this delegate, and we want to infer it from the various 
1804                 // returns (implicit and explicit) from the body of this anonymous
1805                 // method.
1806                 //
1807                 // for example, the lambda: x => 1
1808                 //
1809                 public AnonymousDelegate (AnonymousMethod am, Type target_type, Location l)
1810                 {
1811                         type = target_type;
1812                         loc = l;
1813                         this.am = am;
1814                 }
1815
1816                 public override Expression DoResolve (EmitContext ec)
1817                 {
1818                         eclass = ExprClass.Value;
1819
1820                         //
1821                         // If we are inferencing
1822                         //
1823                         if (type == null){
1824                                 type = ec.ReturnType;
1825
1826                                 // No type was infered
1827                                 if (type == null)
1828                                         return null;
1829                         }
1830
1831                         return this;
1832                 }
1833                 
1834                 public override void Emit (EmitContext ec)
1835                 {
1836                         //ec.ig.Emit (OpCodes.Ldstr, "EMIT ANONYMOUS DELEGATE");
1837                         //ec.ig.Emit (OpCodes.Pop);
1838
1839                         //
1840                         // Now emit the delegate creation.
1841                         //
1842                         if ((am.Method.ModFlags & Modifiers.STATIC) == 0) {
1843                                 Report.Debug (128, "EMIT ANONYMOUS DELEGATE", this, am, am.Scope, loc);
1844                                 delegate_instance_expression = am.Scope.GetScopeInitializer (ec);
1845
1846                                 if (delegate_instance_expression == null)
1847                                         throw new InternalErrorException ();
1848                         }
1849
1850                         Expression ml = Expression.MemberLookup (
1851                                 ec.ContainerType, type, ".ctor", MemberTypes.Constructor,
1852                                 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
1853                                 loc);
1854
1855                         constructor_method = ((MethodGroupExpr) ml).Methods [0];
1856 #if MS_COMPATIBLE
1857                         if (type.IsGenericType)
1858                                 constructor_method = TypeBuilder.GetConstructor (type, (ConstructorInfo)constructor_method);
1859 #endif
1860                         
1861                         delegate_method = am.GetMethodBuilder (ec);
1862                         base.Emit (ec);
1863
1864                         //ec.ig.Emit (OpCodes.Ldstr, "EMIT ANONYMOUS DELEGATE DONE");
1865                         //ec.ig.Emit (OpCodes.Pop);
1866
1867                         Report.Debug (128, "EMIT ANONYMOUS DELEGATE DONE", this, am, am.Scope, loc);
1868                 }
1869         }
1870         
1871         public class AnonymousClass : CompilerGeneratedClass
1872         {
1873                 public AnonymousClass (TypeContainer parent, Location loc)
1874                         : base (parent, null, 0, loc)
1875                 {
1876                 }
1877         }
1878 }