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