Merge with Hari's Lambda
[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 String.Format ("<>c__{0}{1}", 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, 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                 protected ScopeInfo (Block block, DeclSpace parent, GenericMethod generic)
226                         : base (parent, generic, 0, block.StartLocation)
227                 {
228                         Parent = parent;
229                         RootScope = block.Toplevel.RootScope;
230                         ScopeBlock = block;
231
232                         Report.Debug (128, "NEW SCOPE", this, block,
233                                       block.Parent, block.Toplevel);
234
235                         RootScope.AddScope (this);
236                 }
237
238                 protected ScopeInfo (ToplevelBlock toplevel, DeclSpace parent,
239                                      GenericMethod generic, Location loc)
240                         : base (parent, generic, 0, loc)
241                 {
242                         Parent = parent;
243                         RootScope = (RootScopeInfo) this;
244                         ScopeBlock = toplevel;
245
246                         Report.Debug (128, "NEW ROOT SCOPE", this, toplevel, loc);
247                 }
248
249                 protected ScopeInitializer scope_initializer;
250
251                 Hashtable locals = new Hashtable ();
252                 Hashtable captured_scopes = new Hashtable ();
253                 Hashtable captured_params;
254
255                 protected CapturedScope[] CapturedScopes {
256                         get {
257                                 CapturedScope[] list = new CapturedScope [captured_scopes.Count];
258                                 captured_scopes.Values.CopyTo (list, 0);
259                                 return list;
260                         }
261                 }
262
263                 protected CapturedVariable GetCapturedScope (ScopeInfo scope)
264                 {
265                         return (CapturedVariable) captured_scopes [scope];
266                 }
267
268                 public void EmitScopeInstance (EmitContext ec)
269                 {
270                         if (scope_initializer == null) {
271                                 //
272                                 // This is needed if someone overwrites the Emit method
273                                 // of Statement and manually calls Block.Emit without
274                                 // this snippet first:
275                                 // 
276                                 //   ec.EmitScopeInitFromBlock (The_Block);
277                                 //   The_Block.Emit (ec);
278                                 // 
279                                 throw new InternalErrorException ();
280                         }
281
282                         scope_initializer.Emit (ec);
283                 }
284
285                 public ExpressionStatement GetScopeInitializer (EmitContext ec)
286                 {
287                         Report.Debug (128, "GET SCOPE INITIALIZER",
288                                       this, GetType (), scope_initializer, ScopeBlock);
289
290                         if (scope_initializer == null) {
291                                 scope_initializer = CreateScopeInitializer ();
292                                 if (scope_initializer.Resolve (ec) == null)
293                                         throw new InternalErrorException ();
294                         }
295
296                         return scope_initializer;
297                 }
298
299                 public Type GetScopeType (EmitContext ec)
300                 {
301                         if (!IsGeneric)
302                                 return TypeBuilder;
303
304                         TypeArguments targs = new TypeArguments (Location);
305
306                         if (ec.DeclContainer.Parent.IsGeneric)
307                                 foreach (TypeParameter t in ec.DeclContainer.Parent.TypeParameters)
308                                         targs.Add (new TypeParameterExpr (t, Location));
309                         if (ec.DeclContainer.IsGeneric)
310                                 foreach (TypeParameter t in ec.DeclContainer.CurrentTypeParameters)
311                                         targs.Add (new TypeParameterExpr (t, Location));
312
313                         Report.Debug (128, "GET SCOPE TYPE", this, TypeBuilder, targs,
314                                       ec.DeclContainer, ec.DeclContainer.GetType (),
315                                       ec.DeclContainer.Parent.Name);
316
317                         TypeExpr te = new ConstructedType (TypeBuilder, targs, Location);
318                         te = te.ResolveAsTypeTerminal (ec, false);
319                         if ((te == null) || (te.Type == null))
320                                 return null;
321                         return te.Type;
322                 }
323
324                 protected override bool DoDefineMembers ()
325                 {
326                         Report.Debug (64, "SCOPE INFO DEFINE MEMBERS", this, GetType (), IsGeneric,
327                                       Parent.IsGeneric, GenericMethod);
328
329                         foreach (CapturedScope child in CapturedScopes) {
330                                 if (!child.DefineMembers ())
331                                         return false;
332                         }
333
334                         return base.DoDefineMembers ();
335                 }
336
337                 protected override bool DoResolveMembers ()
338                 {
339                         Report.Debug (64, "SCOPE INFO RESOLVE MEMBERS", this, GetType (), IsGeneric,
340                                       Parent.IsGeneric, GenericMethod);
341
342                         return base.DoResolveMembers ();
343                 }
344
345                 public Variable CaptureScope (ScopeInfo child)
346                 {
347                         CheckMembersDefined ();
348                         Report.Debug (128, "CAPTURE SCOPE", this, GetType (), child, child.GetType ());
349                         if (child == this)
350                                 throw new InternalErrorException ();
351                         CapturedScope captured = (CapturedScope) captured_scopes [child];
352                         if (captured == null) {
353                                 captured = new CapturedScope (this, child);
354                                 captured_scopes.Add (child, captured);
355                         }
356                         return captured;
357                 }
358
359                 public Variable AddLocal (LocalInfo local)
360                 {
361                         Report.Debug (128, "CAPTURE LOCAL", this, local);
362                         Variable var = (Variable) locals [local];
363                         if (var == null) {
364                                 var = new CapturedLocal (this, local);
365                                 locals.Add (local, var);
366                                 local.IsCaptured = true;
367                         }
368                         return var;
369                 }
370
371                 public Variable GetCapturedVariable (LocalInfo local)
372                 {
373                         return (Variable) locals [local];
374                 }
375
376                 public bool HostsParameters {
377                         get { return captured_params != null; }
378                 }
379
380                 public Variable GetCapturedParameter (Parameter par)
381                 {
382                         if (captured_params != null)
383                                 return (Variable) captured_params [par];
384                         else
385                                 return null;
386                 }
387
388                 public bool IsParameterCaptured (string name)
389                 {                       
390                         if (captured_params != null)
391                                 return captured_params [name] != null;
392                         return false;
393                 }
394
395                 public Variable AddParameter (Parameter par, int idx)
396                 {
397                         if (captured_params == null)
398                                 captured_params = new Hashtable ();
399
400                         Variable var = (Variable) captured_params [par];
401                         if (var == null) {
402                                 var = new CapturedParameter (this, par, idx);
403                                 captured_params.Add (par, var);
404                                 par.IsCaptured = true;
405                         }
406
407                         return var;
408                 }
409
410                 protected string MakeFieldName (string local_name)
411                 {
412                         return "<" + ID + ":" + local_name + ">";
413                 }
414
415                 protected virtual ScopeInitializer CreateScopeInitializer ()
416                 {
417                         return new ScopeInitializer (this);
418                 }
419
420                 protected abstract class CapturedVariable : Variable
421                 {
422                         public readonly ScopeInfo Scope;
423                         public readonly string Name;
424
425                         public FieldExpr FieldInstance;
426                         protected Field field;
427
428                         protected CapturedVariable (ScopeInfo scope, string name)
429                         {
430                                 this.Scope = scope;
431                                 this.Name = name;
432                         }
433
434                         protected CapturedVariable (ScopeInfo scope, string name, Type type)
435                                 : this (scope, name)
436                         {
437                                 this.field = scope.CaptureVariable (
438                                         scope.MakeFieldName (name), scope.RootScope.InflateType (type));
439                         }
440
441                         public Field Field {
442                                 get { return field; }
443                         }
444
445                         public override Type Type {
446                                 get { return Field.MemberType; }
447                         }
448
449                         public override bool HasInstance {
450                                 get { return true; }
451                         }
452
453                         public override bool NeedsTemporary {
454                                 get { return true; }
455                         }
456
457                         protected FieldInfo GetField (EmitContext ec)
458                         {
459                                 if ((ec.CurrentBlock != null) &&
460                                     (ec.CurrentBlock.Toplevel != Scope.ScopeBlock.Toplevel))
461                                         return Field.FieldBuilder;
462                                 else
463                                         return FieldInstance.FieldInfo;
464                         }
465
466                         public override void EmitInstance (EmitContext ec)
467                         {
468                                 Scope.EmitScopeInstance (ec);
469                         }
470
471                         public override void Emit (EmitContext ec)
472                         {
473                                 ec.ig.Emit (OpCodes.Ldfld, GetField (ec));
474                         }
475
476                         public override void EmitAssign (EmitContext ec)
477                         {
478                                 ec.ig.Emit (OpCodes.Stfld, GetField (ec));
479                         }
480
481                         public override void EmitAddressOf (EmitContext ec)
482                         {
483                                 ec.ig.Emit (OpCodes.Ldflda, GetField (ec));
484                         }
485                 }
486
487                 protected class CapturedParameter : CapturedVariable {
488                         public readonly Parameter Parameter;
489                         public readonly int Idx;
490
491                         public CapturedParameter (ScopeInfo scope, Parameter par, int idx)
492                                 : base (scope, par.Name, par.ParameterType)
493                         {
494                                 this.Parameter = par;
495                                 this.Idx = idx;
496                         }
497
498                         public override string ToString ()
499                         {
500                                 return String.Format ("{0} ({1}:{2}:{3})", GetType (), Field,
501                                                       Parameter.Name, Idx);
502                         }
503                 }
504
505                 protected class CapturedLocal : CapturedVariable {
506                         public readonly LocalInfo Local;
507
508                         public CapturedLocal (ScopeInfo scope, LocalInfo local)
509                                 : base (scope, local.Name, local.VariableType)
510                         {
511                                 this.Local = local;
512                         }
513
514                         public override string ToString ()
515                         {
516                                 return String.Format ("{0} ({1}:{2})", GetType (), Field,
517                                                       Local.Name);
518                         }
519                 }
520
521                 protected class CapturedThis : CapturedVariable {
522                         public CapturedThis (RootScopeInfo host)
523                                 : base (host, "<>THIS", host.ParentType)
524                         { }
525                 }
526
527                 protected class CapturedScope : CapturedVariable {
528                         public readonly ScopeInfo ChildScope;
529
530                         public CapturedScope (ScopeInfo root, ScopeInfo child)
531                                 : base (root, "scope" + child.ID)
532                         {
533                                 this.ChildScope = child;
534                         }
535
536                         public bool DefineMembers ()
537                         {
538                                 Type type = ChildScope.IsGeneric ?
539                                         ChildScope.CurrentType : ChildScope.TypeBuilder;
540                                 Report.Debug (128, "CAPTURED SCOPE DEFINE MEMBERS", this, Scope,
541                                               ChildScope, Name, type);
542                                 if (type == null)
543                                         throw new InternalErrorException ();
544                                 field = Scope.CaptureVariable (
545                                         Scope.MakeFieldName (Name), Scope.InflateType (type));
546                                 return true;
547                         }
548
549                         public override string ToString ()
550                         {
551                                 return String.Format ("CapturedScope ({1} captured in {0})",
552                                                       Scope, ChildScope);
553                         }
554                 }
555
556                 static void DoPath (StringBuilder sb, ScopeInfo start)
557                 {
558                         sb.Append ((start.ID).ToString ());
559                 }
560                 
561                 public override string ToString ()
562                 {
563                         StringBuilder sb = new StringBuilder ();
564                         
565                         sb.Append ("{");
566                         DoPath (sb, this);
567                         sb.Append ("}");
568
569                         return sb.ToString ();
570                 }
571
572                 protected class ScopeInitializer : ExpressionStatement
573                 {
574                         ScopeInfo scope;
575                         CapturedVariable captured_scope;
576                         LocalBuilder scope_instance;
577                         ConstructorInfo scope_ctor;
578
579                         bool initialized;
580
581                         public ScopeInitializer (ScopeInfo scope)
582                         {
583                                 this.scope = scope;
584                                 this.loc = scope.Location;
585                                 eclass = ExprClass.Value;
586                         }
587
588                         public ScopeInfo Scope {
589                                 get { return scope; }
590                         }
591
592                         public override Expression DoResolve (EmitContext ec)
593                         {
594                                 if (scope_ctor != null)
595                                         return this;
596
597                                 Report.Debug (64, "RESOLVE SCOPE INITIALIZER BASE", this, Scope,
598                                               ec, ec.CurrentBlock);
599
600                                 type = Scope.GetScopeType (ec);
601                                 if (type == null)
602                                         throw new InternalErrorException ();
603
604                                 if (!DoResolveInternal (ec))
605                                         throw new InternalErrorException ();
606
607                                 return this;
608                         }
609
610                         protected virtual bool DoResolveInternal (EmitContext ec)
611                         {
612                                 MethodGroupExpr mg = (MethodGroupExpr) Expression.MemberLookupFinal (
613                                         ec, ec.ContainerType, type, ".ctor", MemberTypes.Constructor,
614                                         AllBindingFlags | BindingFlags.DeclaredOnly, loc);
615                                 if (mg == null)
616                                         throw new InternalErrorException ();
617
618                                 scope_ctor = (ConstructorInfo) mg.Methods [0];
619
620                                 Report.Debug (128, "RESOLVE THE INIT", this, Scope, Scope.RootScope,
621                                               Scope.RootScope.GetType ());
622
623                                 ScopeInfo host = Scope.RootScope;
624                                 if ((Scope != host) && (Scope.RootScope is IteratorHost)) {
625                                         captured_scope = host.GetCapturedScope (Scope);
626                                         Type root = host.GetScopeType (ec);
627                                         FieldExpr fe = (FieldExpr) Expression.MemberLookup (
628                                                 type, root, captured_scope.Field.Name, loc);
629                                         if (fe == null)
630                                                 throw new InternalErrorException ();
631
632                                         fe.InstanceExpression = this;
633                                         captured_scope.FieldInstance = fe;
634
635                                         Report.Debug (128, "RESOLVE THE INIT #1", this,
636                                                       captured_scope, fe);
637                                 } else
638                                         scope_instance = ec.ig.DeclareLocal (type);
639
640                                 foreach (CapturedLocal local in Scope.locals.Values) {
641                                         FieldExpr fe = (FieldExpr) Expression.MemberLookup (
642                                                 ec.ContainerType, type, local.Field.Name, loc);
643                                         Report.Debug (64, "RESOLVE SCOPE INITIALIZER #2", this, Scope,
644                                                       Scope, ec, ec.ContainerType, type,
645                                                       local.Field, local.Field.Name, loc, fe);
646                                         if (fe == null)
647                                                 throw new InternalErrorException ();
648
649                                         fe.InstanceExpression = this;
650                                         local.FieldInstance = fe;
651                                 }
652
653                                 if (Scope.HostsParameters) {
654                                         foreach (CapturedParameter cp in Scope.captured_params.Values) {
655                                                 FieldExpr fe = (FieldExpr) Expression.MemberLookup (
656                                                         ec.ContainerType, type, cp.Field.Name, loc);
657                                                 if (fe == null)
658                                                         throw new InternalErrorException ();
659
660                                                 fe.InstanceExpression = this;
661                                                 cp.FieldInstance = fe;
662                                         }
663                                 }
664
665                                 foreach (CapturedScope scope in Scope.CapturedScopes) {
666                                         FieldExpr fe = (FieldExpr) Expression.MemberLookup (
667                                                 ec.ContainerType, type, scope.Field.Name, loc);
668                                         Report.Debug (64, "RESOLVE SCOPE INITIALIZER #3", this, Scope,
669                                                       scope, ec, ec.ContainerType, type,
670                                                       scope.Field, scope.Field.Name, loc, fe);
671                                         if (fe == null)
672                                                 throw new InternalErrorException ();
673
674                                         fe.InstanceExpression = this;
675                                         scope.FieldInstance = fe;
676                                 }
677
678                                 return true;
679                         }
680
681                         protected virtual void EmitParameterReference (EmitContext ec,
682                                                                        CapturedParameter cp)
683                         {
684                                 int extra = ec.MethodIsStatic ? 0 : 1;
685                                 ParameterReference.EmitLdArg (ec.ig, cp.Idx + extra);
686                         }
687
688                         static int next_id;
689                         int id = ++next_id;
690
691                         protected virtual void DoEmit (EmitContext ec)
692                         {
693                                 if ((ec.CurrentBlock != null) &&
694                                     (ec.CurrentBlock.Toplevel != Scope.ScopeBlock.Toplevel)) {
695                                         ec.ig.Emit (OpCodes.Ldarg_0);
696
697                                         if (ec.CurrentAnonymousMethod != null) {
698                                                 ScopeInfo host = ec.CurrentAnonymousMethod.Scope;
699                                                 Variable captured = host.GetCapturedScope (scope);
700                                                 Report.Debug (128, "EMIT SCOPE INSTANCE #2",
701                                                               ec.CurrentAnonymousMethod, host,
702                                                               scope, captured);
703                                                 if (captured != null)
704                                                         captured.Emit (ec);
705                                         }
706                                 } else if (scope_instance != null)
707                                         ec.ig.Emit (OpCodes.Ldloc, scope_instance);
708                                 else {
709                                         Report.Debug (128, "DO EMIT", this, Scope, ec,
710                                                       scope_instance, captured_scope);
711                                         captured_scope.EmitInstance (ec);
712                                         captured_scope.Emit (ec);
713                                 }
714                         }
715
716                         protected void DoEmitInstance (EmitContext ec)
717                         {
718                                 Report.Debug (128, "DO EMIT INSTANCE", this, Scope, ec,
719                                               scope_instance, captured_scope);
720
721                                 if (scope_instance != null)
722                                         ec.ig.Emit (OpCodes.Ldloc, scope_instance);
723                                 else
724                                         captured_scope.EmitInstance (ec);
725                         }
726
727                         protected virtual void EmitScopeConstructor (EmitContext ec)
728                         {
729                                 ec.ig.Emit (OpCodes.Newobj, scope_ctor);
730                         }
731
732                         public override void Emit (EmitContext ec)
733                         {
734                                 if (!initialized)
735                                         throw new InternalErrorException (
736                                                 "Scope {0} not initialized yet", scope);
737
738                                 DoEmit (ec);
739                         }
740
741                         public override void EmitStatement (EmitContext ec)
742                         {
743                                 if (initialized)
744                                         return;
745
746                                 DoEmitStatement (ec);
747                                 initialized = true;
748                         }
749
750                         protected virtual void DoEmitStatement (EmitContext ec)
751                         {
752                                 Report.Debug (128, "EMIT SCOPE INITIALIZER STATEMENT", this, id,
753                                               Scope, scope_instance, ec);
754
755                                 ec.ig.Emit (OpCodes.Nop);
756                                 ec.ig.Emit (OpCodes.Ldc_I4, id);
757                                 ec.ig.Emit (OpCodes.Pop);
758                                 ec.ig.Emit (OpCodes.Nop);
759
760                                 if (scope_instance == null)
761                                         ec.ig.Emit (OpCodes.Ldarg_0);
762                                 EmitScopeConstructor (ec);
763                                 if (scope_instance != null)
764                                         ec.ig.Emit (OpCodes.Stloc, scope_instance);
765                                 else
766                                         captured_scope.EmitAssign (ec);
767
768                                 if (Scope.HostsParameters) {
769                                         foreach (CapturedParameter cp in Scope.captured_params.Values) {
770                                                 Report.Debug (128, "EMIT SCOPE INIT #6", this,
771                                                               ec, ec.IsStatic, Scope, cp, cp.Field.Name);
772                                                 DoEmitInstance (ec);
773                                                 EmitParameterReference (ec, cp);
774                                                 ec.ig.Emit (OpCodes.Stfld, cp.FieldInstance.FieldInfo);
775                                         }
776                                 }
777
778                                 if (Scope is IteratorHost)
779                                         return;
780
781                                 foreach (CapturedScope scope in Scope.CapturedScopes) {
782                                         ScopeInfo child = scope.ChildScope;
783
784                                         Report.Debug (128, "EMIT SCOPE INIT #5", this, Scope,
785                                                       scope.Scope, scope.ChildScope);
786
787                                         ExpressionStatement init = child.GetScopeInitializer (ec);
788                                         init.EmitStatement (ec);
789
790                                         DoEmit (ec);
791                                         scope.ChildScope.EmitScopeInstance (ec);
792                                         scope.EmitAssign (ec);
793                                 }
794                         }
795                 }
796         }
797
798         public class RootScopeInfo : ScopeInfo
799         {
800                 public RootScopeInfo (ToplevelBlock toplevel, DeclSpace parent,
801                                       GenericMethod generic, Location loc)
802                         : base (toplevel, parent, generic, loc)
803                 {
804                         scopes = new ArrayList ();
805                 }
806
807                 TypeExpr parent_type;
808                 CapturedVariableField parent_link;
809                 CapturedThis this_variable;
810                 protected ArrayList scopes;
811
812                 public virtual bool IsIterator {
813                         get { return false; }
814                 }
815
816                 public RootScopeInfo ParentHost {
817                         get { return Parent.PartialContainer as RootScopeInfo; }
818                 }
819
820                 public Type ParentType {
821                         get { return parent_type.Type; }
822                 }
823
824                 public Field ParentLink {
825                         get { return parent_link; }
826                 }
827
828                 protected CapturedThis THIS {
829                         get { return this_variable; }
830                 }
831
832                 public Variable CaptureThis ()
833                 {
834                         if (ParentHost != null)
835                                 return ParentHost.CaptureThis ();
836
837                         CheckMembersDefined ();
838                         if (this_variable == null)
839                                 this_variable = new CapturedThis (this);
840                         return this_variable;
841                 }
842
843                 public void AddScope (ScopeInfo scope)
844                 {
845                         scopes.Add (scope);
846                 }
847
848                 bool linked;
849                 public void LinkScopes ()
850                 {
851                         Report.Debug (128, "LINK SCOPES", this, linked, scopes);
852
853                         if (linked)
854                                 return;
855
856                         linked = true;
857                         if (ParentHost != null)
858                                 ParentHost.LinkScopes ();
859
860                         foreach (ScopeInfo si in scopes) {
861                                 if (!si.Define ())
862                                         throw new InternalErrorException ();
863                                 if (si.DefineType () == null)
864                                         throw new InternalErrorException ();
865                                 if (!si.ResolveType ())
866                                         throw new InternalErrorException ();
867                         }
868
869                         foreach (ScopeInfo si in scopes) {
870                                 if (!si.ResolveMembers ())
871                                         throw new InternalErrorException ();
872                                 if (!si.DefineMembers ())
873                                         throw new InternalErrorException ();
874                         }
875                 }
876
877                 protected override ScopeInitializer CreateScopeInitializer ()
878                 {
879                         return new RootScopeInitializer (this);
880                 }
881
882                 protected override bool DefineNestedTypes ()
883                 {
884                         if (Parent.IsGeneric) {
885                                 parent_type = new ConstructedType (
886                                         Parent.TypeBuilder, Parent.TypeParameters, Location);
887                                 parent_type = parent_type.ResolveAsTypeTerminal (this, false);
888                                 if ((parent_type == null) || (parent_type.Type == null))
889                                         return false;
890                         } else {
891                                 parent_type = new TypeExpression (Parent.TypeBuilder, Location);
892                         }
893
894                         CompilerGeneratedClass parent = Parent.PartialContainer as CompilerGeneratedClass;
895                         if (parent != null)
896                                 parent_link = new CapturedVariableField (this, "<>parent", parent_type);
897
898                         return base.DefineNestedTypes ();
899                 }
900
901                 protected override bool DoDefineMembers ()
902                 {
903                         ArrayList args = new ArrayList ();
904                         if (this is IteratorHost)
905                                 args.Add (new Parameter (
906                                         TypeManager.int32_type, "$PC", Parameter.Modifier.NONE,
907                                         null, Location));
908
909                         Field pfield;
910                         if (Parent is CompilerGeneratedClass)
911                                 pfield = parent_link;
912                         else
913                                 pfield = this_variable !=  null ? this_variable.Field : null;
914                         if (pfield != null)
915                                 args.Add (new Parameter (
916                                         pfield.MemberType, "parent", Parameter.Modifier.NONE,
917                                         null, Location));
918
919                         Parameter[] ctor_params = new Parameter [args.Count];
920                         args.CopyTo (ctor_params, 0);
921                         Constructor ctor = new Constructor (
922                                 this, MemberName.Name, Modifiers.PUBLIC,
923                                 new Parameters (ctor_params),
924                                 new GeneratedBaseInitializer (Location),
925                                 Location);
926                         AddConstructor (ctor);
927
928                         ctor.Block = new ToplevelBlock (null, Location);
929                         ctor.Block.AddStatement (new TheCtor (this));
930
931                         return base.DoDefineMembers ();
932                 }
933
934                 protected virtual void EmitScopeConstructor (EmitContext ec)
935                 {
936                         int pos = (this is IteratorHost) ? 2 : 1;
937
938                         Field pfield;
939                         if (Parent is CompilerGeneratedClass)
940                                 pfield = parent_link;
941                         else
942                                 pfield = this_variable !=  null ? this_variable.Field : null;
943
944                         if (pfield != null) {
945                                 ec.ig.Emit (OpCodes.Ldarg_0);
946                                 ec.ig.Emit (OpCodes.Ldarg, pos);
947                                 ec.ig.Emit (OpCodes.Stfld, pfield.FieldBuilder);
948                                 pos++;
949                         }
950                 }
951
952                 protected class TheCtor : Statement
953                 {
954                         RootScopeInfo host;
955
956                         public TheCtor (RootScopeInfo host)
957                         {
958                                 this.host = host;
959                         }
960
961                         public override bool Resolve (EmitContext ec)
962                         {
963                                 return true;
964                         }
965
966                         protected override void DoEmit (EmitContext ec)
967                         {
968                                 host.EmitScopeConstructor (ec);
969                         }
970                 }
971
972                 protected class RootScopeInitializer : ScopeInitializer
973                 {
974                         RootScopeInfo host;
975
976                         public RootScopeInitializer (RootScopeInfo host)
977                                 : base (host)
978                         {
979                                 this.host = host;
980                         }
981
982                         public RootScopeInfo Host {
983                                 get { return host; }
984                         }
985
986                         protected override bool DoResolveInternal (EmitContext ec)
987                         {
988                                 Report.Debug (64, "RESOLVE ANONYMOUS METHOD HOST INITIALIZER",
989                                               this, Host, Host.ParentType, loc);
990
991                                 if (Host.THIS != null) {
992                                         FieldExpr fe = (FieldExpr) Expression.MemberLookup (
993                                                 ec.ContainerType, type, Host.THIS.Field.Name, loc);
994                                         if (fe == null)
995                                                 throw new InternalErrorException ();
996
997                                         fe.InstanceExpression = this;
998                                         Host.THIS.FieldInstance = fe;
999                                 }
1000
1001                                 return base.DoResolveInternal (ec);
1002                         }
1003
1004                         protected virtual bool IsGetEnumerator {
1005                                 get { return false; }
1006                         }
1007
1008                         protected override void EmitScopeConstructor (EmitContext ec)
1009                         {
1010                                 if (host.THIS != null) {
1011                                         ec.ig.Emit (OpCodes.Ldarg_0);
1012                                         if (IsGetEnumerator)
1013                                                 ec.ig.Emit (OpCodes.Ldfld, host.THIS.Field.FieldBuilder);
1014                                         else if (host.THIS.Type.IsValueType)
1015                                                 Expression.LoadFromPtr (ec.ig, host.THIS.Type);
1016                                 } else if (host.ParentLink != null)
1017                                         ec.ig.Emit (OpCodes.Ldarg_0);
1018
1019                                 base.EmitScopeConstructor (ec);
1020                         }
1021                 }
1022
1023         }
1024
1025         public interface IAnonymousContainer
1026         {
1027                 Block Container {
1028                         get;
1029                 }
1030
1031                 GenericMethod GenericMethod {
1032                         get;
1033                 }
1034
1035                 RootScopeInfo RootScope {
1036                         get;
1037                 }
1038
1039                 bool IsIterator {
1040                         get;
1041                 }
1042         }
1043
1044         public interface IAnonymousHost
1045         {
1046                 //
1047                 // Invoked if a yield statement is found in the body
1048                 //
1049                 void SetYields ();
1050
1051                 //
1052                 // Invoked if an anonymous method is found in the body
1053                 //
1054                 void AddAnonymousMethod (AnonymousMethodExpression anonymous);
1055         }
1056
1057         public class AnonymousMethodExpression : Expression, IAnonymousContainer, IAnonymousHost
1058         {
1059                 public readonly AnonymousMethodExpression Parent;
1060                 public readonly TypeContainer Host;
1061                 public readonly Parameters Parameters;
1062
1063                 public ToplevelBlock Block;
1064                 protected AnonymousMethod anonymous;
1065
1066                 protected readonly Block container;
1067                 protected readonly GenericMethod generic;
1068
1069                 public Block Container {
1070                         get { return container; }
1071                 }
1072
1073                 public GenericMethod GenericMethod {
1074                         get { return generic; }
1075                 }
1076
1077                 public AnonymousMethod AnonymousMethod {
1078                         get { return anonymous; }
1079                 }
1080
1081                 public RootScopeInfo RootScope {
1082                         get { return root_scope; }
1083                 }
1084
1085                 public AnonymousMethodExpression (AnonymousMethodExpression parent,
1086                                                   GenericMethod generic, TypeContainer host,
1087                                                   Parameters parameters, Block container,
1088                                                   Location loc)
1089                 {
1090                         this.Parent = parent;
1091                         this.generic = parent != null ? null : generic;
1092                         this.Host = host;
1093                         this.Parameters = parameters;
1094                         this.container = container;
1095                         this.loc = loc;
1096
1097                         Report.Debug (64, "NEW ANONYMOUS METHOD EXPRESSION", this, parent, host,
1098                                       container, loc);
1099
1100                         if (parent != null)
1101                                 parent.AddAnonymousMethod (this);
1102                 }
1103
1104                 ArrayList children;
1105                 RootScopeInfo root_scope;
1106
1107                 static int next_index;
1108
1109                 void IAnonymousHost.SetYields ()
1110                 {
1111                         throw new InvalidOperationException ();
1112                 }
1113
1114                 public void AddAnonymousMethod (AnonymousMethodExpression anonymous)
1115                 {
1116                         if (children == null)
1117                                 children = new ArrayList ();
1118                         children.Add (anonymous);
1119                 }
1120
1121                 public bool CreateAnonymousHelpers ()
1122                 {
1123                         Report.Debug (64, "ANONYMOUS METHOD EXPRESSION CREATE ROOT SCOPE",
1124                                       this, Host, container, loc);
1125
1126                         if (container != null)
1127                                 root_scope = container.Toplevel.CreateRootScope (Host);
1128
1129                         if (children != null) {
1130                                 foreach (AnonymousMethodExpression child in children) {
1131                                         if (!child.CreateAnonymousHelpers ())
1132                                                 return false;
1133                                 }
1134                         }
1135
1136                         return true;
1137                 }
1138
1139                 public override string ExprClassName {
1140                         get {
1141                                 return "anonymous method";
1142                         }
1143                 }
1144
1145                 void Error_ParameterMismatch (Type t)
1146                 {
1147                         Report.Error (1661, loc, "Anonymous method could not be converted to delegate `" +
1148                                       "{0}' since there is a parameter mismatch",
1149                                       TypeManager.CSharpName (t));
1150                 }
1151
1152                 public bool ImplicitStandardConversionExists (Type delegate_type)
1153                 {
1154                         if (Parameters == null)
1155                                 return true;
1156
1157                         MethodGroupExpr invoke_mg = Delegate.GetInvokeMethod (
1158                                 Host.TypeBuilder, delegate_type, loc);
1159                         MethodInfo invoke_mb = (MethodInfo) invoke_mg.Methods [0];
1160                         ParameterData invoke_pd = TypeManager.GetParameterData (invoke_mb);
1161
1162                         if (Parameters.Count != invoke_pd.Count)
1163                                 return false;
1164
1165                         for (int i = 0; i < Parameters.Count; ++i) {
1166                                 if (invoke_pd.ParameterType (i) != Parameters.ParameterType (i))
1167                                         return false;
1168                         }
1169                         return true;
1170                 }
1171
1172                 //
1173                 // Returns true if this anonymous method can be implicitly
1174                 // converted to the delegate type `delegate_type'
1175                 //
1176                 public Expression Compatible (EmitContext ec, Type delegate_type)
1177                 {
1178                         if (anonymous != null)
1179                                 return anonymous.AnonymousDelegate;
1180
1181                         if (!ec.IsAnonymousMethodAllowed) {
1182                                 Report.Error (1706, loc,
1183                                               "Anonymous methods are not allowed in the " +
1184                                               "attribute declaration");
1185                                 return null;
1186                         }
1187
1188                         if (!TypeManager.IsDelegateType (delegate_type)){
1189                                 Report.Error (1660, loc,
1190                                               "Cannot convert anonymous method block to type " +
1191                                               "`{0}' because it is not a delegate type",
1192                                               TypeManager.CSharpName (delegate_type));
1193                                 return null;
1194                         }
1195
1196                         //
1197                         // At this point its the first time we know the return type that is 
1198                         // needed for the anonymous method.  We create the method here.
1199                         //
1200
1201                         MethodGroupExpr invoke_mg = Delegate.GetInvokeMethod (
1202                                 ec.ContainerType, delegate_type, loc);
1203                         MethodInfo invoke_mb = (MethodInfo) invoke_mg.Methods [0];
1204                         ParameterData invoke_pd = TypeManager.GetParameterData (invoke_mb);
1205
1206                         Parameters parameters;
1207                         if (Parameters == null) {
1208                                 //
1209                                 // We provide a set of inaccessible parameters
1210                                 //
1211                                 Parameter [] fixedpars = new Parameter [invoke_pd.Count];
1212                                                                 
1213                                 for (int i = 0; i < invoke_pd.Count; i++) {
1214                                         Parameter.Modifier i_mod = invoke_pd.ParameterModifier (i);
1215                                         if ((i_mod & Parameter.Modifier.OUTMASK) != 0) {
1216                                                 Report.Error (1688, loc, "Cannot convert anonymous " +
1217                                                               "method block without a parameter list " +
1218                                                               "to delegate type `{0}' because it has " +
1219                                                               "one or more `out' parameters.",
1220                                                               TypeManager.CSharpName (delegate_type));
1221                                                 return null;
1222                                         }
1223                                         fixedpars [i] = new Parameter (
1224                                                 invoke_pd.ParameterType (i), "+" + (++next_index),
1225                                                 invoke_pd.ParameterModifier (i), null, loc);
1226                                 }
1227                                                                 
1228                                 parameters = new Parameters (fixedpars);
1229                                 if (!parameters.Resolve (ec))
1230                                         return null;
1231                         } else {
1232                                 if (Parameters.Count != invoke_pd.Count) {
1233                                         Report.SymbolRelatedToPreviousError (delegate_type);
1234                                         Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments",
1235                                                 TypeManager.CSharpName (delegate_type), Parameters.Count.ToString ());
1236                                         Error_ParameterMismatch (delegate_type);
1237                                         return null;
1238                                 }
1239
1240                                 for (int i = 0; i < Parameters.Count; ++i) {
1241                                         Parameter.Modifier p_mod = invoke_pd.ParameterModifier (i);
1242                                         if (Parameters.ParameterModifier (i) != p_mod && p_mod != Parameter.Modifier.PARAMS) {
1243                                                 if (p_mod == Parameter.Modifier.NONE)
1244                                                         Report.Error (1677, loc, "Parameter `{0}' should not be declared with the `{1}' keyword",
1245                                                                 (i + 1).ToString (), Parameter.GetModifierSignature (Parameters.ParameterModifier (i)));
1246                                                 else
1247                                                         Report.Error (1676, loc, "Parameter `{0}' must be declared with the `{1}' keyword",
1248                                                                 (i+1).ToString (), Parameter.GetModifierSignature (p_mod));
1249                                                 Error_ParameterMismatch (delegate_type);
1250                                                 return null;
1251                                         }
1252
1253                                         if (invoke_pd.ParameterType (i) != Parameters.ParameterType (i)) {
1254                                                 Report.Error (1678, loc, "Parameter `{0}' is declared as type `{1}' but should be `{2}'",
1255                                                         (i+1).ToString (),
1256                                                         TypeManager.CSharpName (Parameters.ParameterType (i)),
1257                                                         TypeManager.CSharpName (invoke_pd.ParameterType (i)));
1258                                                 Error_ParameterMismatch (delegate_type);
1259                                                 return null;
1260                                         }
1261                                 }
1262
1263                                 parameters = Parameters;
1264                         }
1265
1266                         //
1267                         // Second: the return type of the delegate must be compatible with 
1268                         // the anonymous type.   Instead of doing a pass to examine the block
1269                         // we satisfy the rule by setting the return type on the EmitContext
1270                         // to be the delegate type return type.
1271                         //
1272
1273                         //MethodBuilder builder = method_data.MethodBuilder;
1274                         //ILGenerator ig = builder.GetILGenerator ();
1275
1276                         Report.Debug (64, "COMPATIBLE", this, Parent, GenericMethod, Host,
1277                                       Container, Block, invoke_mb.ReturnType, delegate_type,
1278                                       TypeManager.IsGenericType (delegate_type), loc);
1279
1280                         anonymous = new AnonymousMethod (
1281                                 Parent != null ? Parent.AnonymousMethod : null, RootScope, Host,
1282                                 GenericMethod, parameters, Container, Block, invoke_mb.ReturnType,
1283                                 delegate_type, loc);
1284
1285                         if (!anonymous.Resolve (ec))
1286                                 return null;
1287
1288                         return anonymous.AnonymousDelegate;
1289                 }
1290
1291                 public override Expression DoResolve (EmitContext ec)
1292                 {
1293                         //
1294                         // Set class type, set type
1295                         //
1296
1297                         eclass = ExprClass.Value;
1298
1299                         //
1300                         // This hack means `The type is not accessible
1301                         // anywhere', we depend on special conversion
1302                         // rules.
1303                         // 
1304                         type = TypeManager.anonymous_method_type;
1305
1306                         if ((Parameters != null) && !Parameters.Resolve (ec))
1307                                 return null;
1308
1309                         return this;
1310                 }
1311
1312                 public override void Emit (EmitContext ec)
1313                 {
1314                         // nothing, as we only exist to not do anything.
1315                 }
1316
1317                 public bool IsIterator {
1318                         get { return false; }
1319                 }
1320         }
1321
1322         public abstract class AnonymousContainer : IAnonymousContainer
1323         {
1324                 public readonly Location Location;
1325
1326                 public Parameters Parameters;
1327
1328                 //
1329                 // The block that makes up the body for the anonymous mehtod
1330                 //
1331                 public readonly ToplevelBlock Block;
1332
1333                 public readonly int ModFlags;
1334                 public Type ReturnType;
1335                 public readonly DeclSpace Host;
1336
1337                 //
1338                 // The implicit method we create
1339                 //
1340                 protected Method method;
1341                 protected EmitContext aec;
1342
1343                 // The emit context for the anonymous method
1344                 protected bool unreachable;
1345                 protected readonly Block container;
1346                 protected readonly GenericMethod generic;
1347
1348                 //
1349                 // Points to our container anonymous method if its present
1350                 //
1351                 public readonly AnonymousContainer ContainerAnonymousMethod;
1352
1353                 protected AnonymousContainer (AnonymousContainer parent, DeclSpace host,
1354                                               GenericMethod generic, Parameters parameters,
1355                                               Block container, ToplevelBlock block,
1356                                               Type return_type, int mod, Location loc)
1357                 {
1358                         this.ContainerAnonymousMethod = parent;
1359                         this.ReturnType = return_type;
1360                         this.ModFlags = mod;
1361                         this.Host = host;
1362
1363                         this.container = container;
1364                         this.generic = parent != null ? null : generic;
1365                         this.Parameters = parameters;
1366                         this.Block = block;
1367                         this.Location = loc;
1368
1369                         block.AnonymousContainer = this;
1370                 }
1371
1372                 public Method Method {
1373                         get { return method; }
1374                 }
1375
1376                 public abstract RootScopeInfo RootScope {
1377                         get;
1378                 }
1379
1380                 public abstract ScopeInfo Scope {
1381                         get;
1382                 }
1383
1384                 public abstract string GetSignatureForError ();
1385
1386                 public virtual bool Resolve (EmitContext ec)
1387                 {
1388                         Report.Debug (64, "RESOLVE ANONYMOUS METHOD", this, Location, ec,
1389                                       RootScope, Parameters, ec.IsStatic);
1390
1391                         if (ReturnType != null) {
1392                                 TypeExpr return_type_expr;
1393                                 if (RootScope != null)
1394                                         return_type_expr = RootScope.InflateType (ReturnType);
1395                                 else
1396                                         return_type_expr = new TypeExpression (ReturnType, Location);
1397                                 return_type_expr = return_type_expr.ResolveAsTypeTerminal (ec, false);
1398                                 if ((return_type_expr == null) || (return_type_expr.Type == null))
1399                                         return false;
1400                                 ReturnType = return_type_expr.Type;
1401                         }
1402
1403                         if (RootScope != null)
1404                                 Parameters = RootScope.InflateParameters (Parameters);
1405
1406                         aec = new EmitContext (
1407                                 ec.ResolveContext, ec.TypeContainer,
1408                                 RootScope != null ? RootScope : Host, Location, null, ReturnType,
1409                                 /* REVIEW */ (ec.InIterator ? Modifiers.METHOD_YIELDS : 0) |
1410                                 (ec.InUnsafe ? Modifiers.UNSAFE : 0), /* No constructor */ false);
1411
1412                         aec.CurrentAnonymousMethod = this;
1413                         aec.IsFieldInitializer = ec.IsFieldInitializer;
1414                         aec.IsStatic = ec.IsStatic;
1415
1416                         Report.Debug (64, "RESOLVE ANONYMOUS METHOD #1", this, Location, ec, aec,
1417                                       RootScope, Parameters, Block);
1418
1419                         bool unreachable;
1420                         if (!aec.ResolveTopBlock (ec, Block, Parameters, null, out unreachable))
1421                                 return false;
1422
1423                         Report.Debug (64, "RESOLVE ANONYMOUS METHOD #3", this, ec, aec, Block);
1424
1425                         method = DoCreateMethodHost (ec);
1426
1427                         if (Scope != null)
1428                                 return true;
1429
1430                         if (!method.ResolveMembers ())
1431                                 return false;
1432                         return method.Define ();
1433                 }
1434
1435                 protected abstract Method DoCreateMethodHost (EmitContext ec);
1436
1437                 public Block Container {
1438                         get { return container; }
1439                 }
1440
1441                 public GenericMethod GenericMethod {
1442                         get { return generic; }
1443                 }
1444
1445                 public abstract bool IsIterator {
1446                         get;
1447                 }
1448
1449                 protected class AnonymousMethodMethod : Method
1450                 {
1451                         public readonly AnonymousContainer AnonymousMethod;
1452                         public readonly ScopeInfo Scope;
1453
1454                         public AnonymousMethodMethod (AnonymousContainer am, ScopeInfo scope,
1455                                                       GenericMethod generic, TypeExpr return_type,
1456                                                       int mod, MemberName name, Parameters parameters)
1457                                 : base (scope != null ? scope : am.Host,
1458                                         generic, return_type, mod, false, name, parameters, null)
1459                         {
1460                                 this.AnonymousMethod = am;
1461                                 this.Scope = scope;
1462
1463                                 if (scope != null) {
1464                                         scope.CheckMembersDefined ();
1465                                         scope.AddMethod (this);
1466                                 } else {
1467                                         ModFlags |= Modifiers.STATIC;
1468                                         am.Host.PartialContainer.AddMethod (this);
1469                                 }
1470                                 Block = am.Block;
1471                         }
1472
1473                         public override EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
1474                         {
1475                                 EmitContext aec = AnonymousMethod.aec;
1476                                 aec.ig = ig;
1477                                 aec.MethodIsStatic = Scope == null;
1478                                 return aec;
1479                         }
1480                 }
1481         }
1482
1483         public class AnonymousMethod : AnonymousContainer
1484         {
1485                 public readonly Type DelegateType;
1486
1487                 //
1488                 // The value return by the Compatible call, this ensure that
1489                 // the code works even if invoked more than once (Resolve called
1490                 // more than once, due to the way Convert.ImplicitConversion works
1491                 //
1492                 Expression anonymous_delegate;
1493                 RootScopeInfo root_scope;
1494                 ScopeInfo scope;
1495
1496                 public AnonymousMethod (AnonymousMethod parent, RootScopeInfo root_scope,
1497                                         DeclSpace host, GenericMethod generic,
1498                                         Parameters parameters, Block container,
1499                                         ToplevelBlock block, Type return_type, Type delegate_type,
1500                                         Location loc)
1501                         : base (parent, host, generic, parameters, container, block,
1502                                 return_type, 0, loc)
1503                 {
1504                         this.DelegateType = delegate_type;
1505                         this.root_scope = root_scope;
1506                 }
1507
1508                 public override RootScopeInfo RootScope {
1509                         get { return root_scope; }
1510                 }
1511
1512                 public override ScopeInfo Scope {
1513                         get { return scope; }
1514                 }
1515
1516                 public override bool IsIterator {
1517                         get { return false; }
1518                 }
1519
1520                 public Expression AnonymousDelegate {
1521                         get { return anonymous_delegate; }
1522                 }
1523
1524                 public override string GetSignatureForError ()
1525                 {
1526                         return TypeManager.CSharpName (DelegateType);
1527                 }
1528
1529                 //
1530                 // Creates the host for the anonymous method
1531                 //
1532                 protected override Method DoCreateMethodHost (EmitContext ec)
1533                 {
1534                         string name = CompilerGeneratedClass.MakeName ("AnonymousMethod");
1535                         MemberName member_name;
1536
1537                         Report.Debug (128, "CREATE METHOD HOST #0", RootScope);
1538
1539                         Block b;
1540                         scope = RootScope;
1541
1542                         Report.Debug (128, "CREATE METHOD HOST #1", this, Block, Block.ScopeInfo,
1543                                       RootScope, Location);
1544
1545                         for (b = Block.Parent; b != null; b = b.Parent) {
1546                                 Report.Debug (128, "CREATE METHOD HOST #2", this, Block,
1547                                               b, b.ScopeInfo);
1548                                 if (b.ScopeInfo != null) {
1549                                         scope = b.ScopeInfo;
1550                                         break;
1551                                 }
1552                         }
1553
1554                         if (scope != null)
1555                                 scope.CheckMembersDefined ();
1556
1557                         ArrayList scopes = new ArrayList ();
1558                         if (b != null) {
1559                                 for (b = b.Parent; b != null; b = b.Parent) {
1560                                         if (b.ScopeInfo != null)
1561                                                 scopes.Add (b.ScopeInfo);
1562                                 }
1563                         }
1564
1565                         Report.Debug (128, "CREATE METHOD HOST #1", this, scope, scopes);
1566
1567                         foreach (ScopeInfo si in scopes)
1568                                 scope.CaptureScope (si);
1569
1570                         Report.Debug (128, "CREATE METHOD HOST", this, Block, container,
1571                                       RootScope, scope, scopes, Location,
1572                                       ContainerAnonymousMethod);
1573
1574                         GenericMethod generic_method = null;
1575 #if GMCS_SOURCE
1576                         if (TypeManager.IsGenericType (DelegateType)) {
1577                                 TypeArguments args = new TypeArguments (Location);
1578
1579                                 Type dt = DelegateType.GetGenericTypeDefinition ();
1580
1581                                 Type[] tparam = TypeManager.GetTypeArguments (dt);
1582                                 for (int i = 0; i < tparam.Length; i++)
1583                                         args.Add (new SimpleName (tparam [i].Name, Location));
1584
1585                                 member_name = new MemberName (name, args, Location);
1586
1587                                 Report.Debug (128, "CREATE METHOD HOST #5", this, DelegateType,
1588                                               TypeManager.GetTypeArguments (DelegateType),
1589                                               dt, tparam, args);
1590
1591                                 generic_method = new GenericMethod (
1592                                         Host.NamespaceEntry, scope, member_name,
1593                                         new TypeExpression (ReturnType, Location), Parameters);
1594
1595                                 generic_method.SetParameterInfo (null);
1596                         } else
1597 #endif
1598                                 member_name = new MemberName (name, Location);
1599
1600                         return new AnonymousMethodMethod (
1601                                 this, scope, generic_method, new TypeExpression (ReturnType, Location),
1602                                 Modifiers.INTERNAL, member_name, Parameters);
1603                 }
1604
1605                 public override bool Resolve (EmitContext ec)
1606                 {
1607                         if (!base.Resolve (ec))
1608                                 return false;
1609
1610                         anonymous_delegate = new AnonymousDelegate (
1611                                 this, DelegateType, Location).Resolve (ec);
1612                         if (anonymous_delegate == null)
1613                                 return false;
1614
1615                         return true;
1616                 }
1617
1618                 public MethodInfo GetMethodBuilder (EmitContext ec)
1619                 {
1620                         MethodInfo builder = method.MethodBuilder;
1621                         if ((Scope != null) && Scope.IsGeneric) {
1622                                 Type scope_type = Scope.GetScopeType (ec);
1623                                 if (scope_type == null)
1624                                         throw new InternalErrorException ();
1625
1626                                 MethodGroupExpr mg = (MethodGroupExpr) Expression.MemberLookup (
1627                                         ec.ContainerType, scope_type, builder.Name, Location);
1628
1629                                 if (mg == null)
1630                                         throw new InternalErrorException ();
1631                                 builder = (MethodInfo) mg.Methods [0];
1632                         }
1633
1634 #if GMCS_SOURCE
1635                         if (!DelegateType.IsGenericType)
1636                                 return builder;
1637
1638                         Type[] targs = TypeManager.GetTypeArguments (DelegateType);
1639                         return builder.MakeGenericMethod (targs);
1640 #else
1641                         return builder;
1642 #endif
1643                 }
1644
1645                 public static void Error_AddressOfCapturedVar (string name, Location loc)
1646                 {
1647                         Report.Error (1686, loc,
1648                                       "Local variable `{0}' or its members cannot have their " +
1649                                       "address taken and be used inside an anonymous method block",
1650                                       name);
1651                 }
1652         }
1653
1654         //
1655         // This will emit the code for the delegate, as well delegate creation on the host
1656         //
1657         public class AnonymousDelegate : DelegateCreation {
1658                 AnonymousMethod am;
1659
1660                 public AnonymousDelegate (AnonymousMethod am, Type target_type, Location l)
1661                 {
1662                         type = target_type;
1663                         loc = l;
1664                         this.am = am;
1665                 }
1666
1667                 public override Expression DoResolve (EmitContext ec)
1668                 {
1669                         eclass = ExprClass.Value;
1670
1671                         return this;
1672                 }
1673                 
1674                 public override void Emit (EmitContext ec)
1675                 {
1676                         //ec.ig.Emit (OpCodes.Ldstr, "EMIT ANONYMOUS DELEGATE");
1677                         //ec.ig.Emit (OpCodes.Pop);
1678
1679                         //
1680                         // Now emit the delegate creation.
1681                         //
1682                         if ((am.Method.ModFlags & Modifiers.STATIC) == 0) {
1683                                 Report.Debug (128, "EMIT ANONYMOUS DELEGATE", this, am, am.Scope, loc);
1684                                 delegate_instance_expression = am.Scope.GetScopeInitializer (ec);
1685
1686                                 if (delegate_instance_expression == null)
1687                                         throw new InternalErrorException ();
1688                         }
1689
1690                         Expression ml = Expression.MemberLookup (
1691                                 ec.ContainerType, type, ".ctor", MemberTypes.Constructor,
1692                                 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
1693                                 loc);
1694
1695                         constructor_method = ((MethodGroupExpr) ml).Methods [0];
1696                         delegate_method = am.GetMethodBuilder (ec);
1697                         base.Emit (ec);
1698
1699                         //ec.ig.Emit (OpCodes.Ldstr, "EMIT ANONYMOUS DELEGATE DONE");
1700                         //ec.ig.Emit (OpCodes.Pop);
1701
1702                         Report.Debug (128, "EMIT ANONYMOUS DELEGATE DONE", this, am, am.Scope, loc);
1703                 }
1704         }
1705 }