2008-02-19 Martin Baulig <martin@ximian.com>
[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 //   Marek Safar (marek.safar@gmail.com)
7 //
8 // (C) 2003, 2004 Novell, Inc.
9 //
10 // TODO: Ideally, we should have the helper classes emited as a hierarchy to map
11 // their nesting, and have the visibility set to private, instead of NestedAssembly
12 //
13 //
14 //
15
16 using System;
17 using System.Text;
18 using System.Collections;
19 using System.Reflection;
20 using System.Reflection.Emit;
21
22 namespace Mono.CSharp {
23
24         public abstract class CompilerGeneratedClass : Class
25         {
26                 GenericMethod generic_method;
27                 static int next_index = 0;
28
29                 private static MemberName MakeProxyName (GenericMethod generic, Location loc)
30                 {
31                         string name = MakeName (null, "CompilerGenerated");
32                         if (generic != null) {
33                                 TypeArguments args = new TypeArguments (loc);
34                                 foreach (TypeParameter tparam in generic.CurrentTypeParameters)
35                                         args.Add (new SimpleName (tparam.Name, loc));
36                                 return new MemberName (name, args, loc);
37                         } else
38                                 return new MemberName (name, loc);
39                 }
40
41                 public static string MakeName (string host, string prefix)
42                 {
43                         return "<" + host + ">c__" + prefix + next_index++;
44                 }
45
46                 protected CompilerGeneratedClass (DeclSpace parent,
47                                         MemberName name, int mod, Location loc) :
48                         base (parent.NamespaceEntry, parent, name, mod | Modifiers.COMPILER_GENERATED, null)
49                 {
50                         parent.PartialContainer.AddCompilerGeneratedClass (this);
51                 }
52
53                 protected CompilerGeneratedClass (DeclSpace parent, GenericMethod generic,
54                                                   int mod, Location loc)
55                         : this (parent, MakeProxyName (generic, loc), mod, loc)
56                 {
57                         this.generic_method = generic;
58
59                         if (generic != null) {
60                                 ArrayList list = new ArrayList ();
61                                 foreach (TypeParameter tparam in generic.TypeParameters) {
62                                         if (tparam.Constraints != null)
63                                                 list.Add (tparam.Constraints.Clone ());
64                                 }
65                                 SetParameterInfo (list);
66                         }
67
68                 }
69
70                 protected override bool DefineNestedTypes ()
71                 {
72                         RootContext.RegisterCompilerGeneratedType (TypeBuilder);
73                         return base.DefineNestedTypes ();
74                 }
75
76                 protected override bool DoDefineMembers ()
77                 {
78                         members_defined = true;
79
80                         if (!base.DoDefineMembers ())
81                                 return false;
82
83                         if (CompilerGenerated != null) {
84                                 foreach (CompilerGeneratedClass c in CompilerGenerated) {
85                                         if (!c.DefineMembers ())
86                                                 throw new InternalErrorException ();
87                                 }
88                         }
89
90                         return true;
91                 }
92
93                 protected override bool DoResolveMembers ()
94                 {
95                         if (CompilerGenerated != null) {
96                                 foreach (CompilerGeneratedClass c in CompilerGenerated) {
97                                         if (!c.ResolveMembers ())
98                                                 return false;
99                                 }
100                         }
101
102                         return base.DoResolveMembers ();
103                 }
104
105                 public GenericMethod GenericMethod {
106                         get { return generic_method; }
107                 }
108
109                 public Parameters InflateParameters (Parameters ps)
110                 {
111                         if (generic_method == null)
112                                 return ps;
113
114                         int n = ps.Count;
115                         if (n == 0)
116                                 return ps;
117
118                         Parameter[] inflated_params = new Parameter [n];
119                         Type[] inflated_types = new Type [n];
120
121                         for (int i = 0; i < n; ++i) {
122                                 Parameter p = ps [i];
123                                 Type it = InflateType (p.ExternalType ()).ResolveAsTypeTerminal (this, false).Type;
124                                 inflated_types [i] = it;
125                                 inflated_params [i] = new Parameter (it, p.Name, p.ModFlags, p.OptAttributes, p.Location);
126                         }
127                         return Parameters.CreateFullyResolved (inflated_params, inflated_types);
128                 }
129
130                 public TypeExpr InflateType (Type it)
131                 {
132 #if GMCS_SOURCE
133                         if (generic_method == null)
134                                 return new TypeExpression (it, Location);
135
136                         if (it.IsGenericParameter && (it.DeclaringMethod != null)) {
137                                 int pos = it.GenericParameterPosition;
138                                 it = CurrentTypeParameters [pos].Type;
139                         } else if (it.IsGenericType) {
140                                 Type[] args = it.GetGenericArguments ();
141
142                                 TypeArguments inflated = new TypeArguments (Location);
143                                 foreach (Type t in args)
144                                         inflated.Add (InflateType (t));
145
146                                 return new ConstructedType (it, inflated, Location);
147                         } else if (it.IsArray) {
148                                 TypeExpr et_expr = InflateType (it.GetElementType ());
149                                 int rank = it.GetArrayRank ();
150
151                                 Type et = et_expr.ResolveAsTypeTerminal (this, false).Type;
152                                 it = et.MakeArrayType (rank);
153                         }
154 #endif
155
156                         return new TypeExpression (it, Location);
157                 }
158
159                 public Field CaptureVariable (string name, TypeExpr type)
160                 {
161                         if (members_defined)
162                                 throw new InternalErrorException ("Helper class already defined!");
163                         if (type == null)
164                                 throw new ArgumentNullException ();
165
166                         return new CapturedVariableField (this, name, type);
167                 }
168
169                 bool members_defined;
170
171                 internal void CheckMembersDefined ()
172                 {
173                         if (members_defined)
174                                 throw new InternalErrorException ("Helper class already defined!");
175                 }
176
177                 protected class CapturedVariableField : Field
178                 {
179                         public CapturedVariableField (CompilerGeneratedClass helper, string name,
180                                                       TypeExpr type)
181                                 : base (helper, type, Modifiers.INTERNAL, name, null, helper.Location)
182                         {
183                                 helper.AddField (this);
184                         }
185                 }
186         }
187
188         public class ScopeInfo : CompilerGeneratedClass
189         {
190                 protected readonly RootScopeInfo RootScope;
191                 new public readonly DeclSpace Parent;
192                 public readonly int ID = ++next_id;
193                 public readonly Block ScopeBlock;
194                 protected ScopeInitializer scope_initializer;
195
196                 readonly Hashtable locals = new Hashtable ();
197                 readonly Hashtable captured_scopes = new Hashtable ();
198                 Hashtable captured_params;
199
200                 static int next_id;
201
202                 public static ScopeInfo CreateScope (Block block)
203                 {
204                         ToplevelBlock toplevel = block.Toplevel;
205                         AnonymousContainer ac = toplevel.AnonymousContainer;
206
207                         Report.Debug (128, "CREATE SCOPE", block, block.ScopeInfo, toplevel, ac);
208
209                         if (ac == null)
210                                 return new ScopeInfo (block, toplevel.RootScope.Parent,
211                                                       toplevel.RootScope.GenericMethod);
212
213                         Report.Debug (128, "CREATE SCOPE #1", ac, ac.Host, ac.Scope, ac.Block,
214                                       ac.Container,
215                                       ac.Location);
216
217                         Block b;
218                         ScopeInfo parent = null;
219
220                         for (b = ac.Block; b != null; b = b.Parent) {
221                                 if (b.ScopeInfo != null) {
222                                         parent = b.ScopeInfo;
223                                         break;
224                                 }
225                         }
226
227                         Report.Debug (128, "CREATE SCOPE #2", parent);
228
229                         ScopeInfo new_scope = new ScopeInfo (block, parent, null);
230
231                         Report.Debug (128, "CREATE SCOPE #3", new_scope);
232
233                         return new_scope;
234                 }
235
236                 private static int default_modflags (DeclSpace parent)
237                 {
238                         return parent is CompilerGeneratedClass ? Modifiers.PUBLIC : Modifiers.PRIVATE;
239                 }
240
241                 protected ScopeInfo (Block block, DeclSpace parent, GenericMethod generic)
242                         : base (parent, generic, default_modflags (parent), block.StartLocation)
243                 {
244                         Parent = parent;
245                         RootScope = block.Toplevel.RootScope;
246                         ScopeBlock = block;
247
248                         Report.Debug (128, "NEW SCOPE", this, block,
249                                       block.Parent, block.Toplevel);
250
251                         RootScope.AddScope (this);
252                 }
253
254                 protected ScopeInfo (ToplevelBlock toplevel, DeclSpace parent,
255                                      GenericMethod generic, Location loc)
256                         : base (parent, generic, default_modflags (parent), loc)
257                 {
258                         Parent = parent;
259                         RootScope = (RootScopeInfo) this;
260                         ScopeBlock = toplevel;
261
262                         Report.Debug (128, "NEW ROOT SCOPE", this, toplevel, loc);
263                 }
264
265                 protected CapturedScope[] CapturedScopes {
266                         get {
267                                 CapturedScope[] list = new CapturedScope [captured_scopes.Count];
268                                 captured_scopes.Values.CopyTo (list, 0);
269                                 return list;
270                         }
271                 }
272
273                 protected CapturedVariable GetCapturedScope (ScopeInfo scope)
274                 {
275                         return (CapturedVariable) captured_scopes [scope];
276                 }
277
278                 protected void EmitScopeInstance (EmitContext ec)
279                 {
280                         if (scope_initializer == null) {
281                                 //
282                                 // This is needed if someone overwrites the Emit method
283                                 // of Statement and manually calls Block.Emit without
284                                 // this snippet first:
285                                 // 
286                                 //   ec.EmitScopeInitFromBlock (The_Block);
287                                 //   The_Block.Emit (ec);
288                                 // 
289                                 throw new InternalErrorException ();
290                         }
291
292                         scope_initializer.Emit (ec);
293                 }
294
295                 public ExpressionStatement GetScopeInitializer (EmitContext ec)
296                 {
297                         Report.Debug (128, "GET SCOPE INITIALIZER",
298                                       this, GetType (), scope_initializer, ScopeBlock);
299
300                         if (scope_initializer == null) {
301                                 scope_initializer = CreateScopeInitializer ();
302                                 if (scope_initializer.Resolve (ec) == null)
303                                         throw new InternalErrorException ();
304                         }
305
306                         return scope_initializer;
307                 }
308
309                 public Type GetScopeType (EmitContext ec)
310                 {
311                         if (!IsGeneric)
312                                 return TypeBuilder;
313
314                         TypeArguments targs = new TypeArguments (Location);
315
316                         if (ec.DeclContainer.Parent.IsGeneric)
317                                 foreach (TypeParameter t in ec.DeclContainer.Parent.TypeParameters)
318                                         targs.Add (new TypeParameterExpr (t, Location));
319                         if (ec.DeclContainer.IsGeneric)
320                                 foreach (TypeParameter t in ec.DeclContainer.CurrentTypeParameters)
321                                         targs.Add (new TypeParameterExpr (t, Location));
322
323                         Report.Debug (128, "GET SCOPE TYPE", this, TypeBuilder, targs,
324                                       ec.DeclContainer, ec.DeclContainer.GetType (),
325                                       ec.DeclContainer.Parent.Name);
326
327                         TypeExpr te = new ConstructedType (TypeBuilder, targs, Location);
328                         te = te.ResolveAsTypeTerminal (ec, false);
329                         if ((te == null) || (te.Type == null))
330                                 return null;
331                         return te.Type;
332                 }
333
334                 protected override bool DoDefineMembers ()
335                 {
336                         Report.Debug (64, "SCOPE INFO DEFINE MEMBERS", this, GetType (), IsGeneric,
337                                       Parent.IsGeneric, GenericMethod);
338
339                         foreach (CapturedScope child in CapturedScopes) {
340                                 if (!child.DefineMembers ())
341                                         return false;
342                         }
343
344                         return base.DoDefineMembers ();
345                 }
346
347                 protected override bool DoResolveMembers ()
348                 {
349                         Report.Debug (64, "SCOPE INFO RESOLVE MEMBERS", this, GetType (), IsGeneric,
350                                       Parent.IsGeneric, GenericMethod);
351
352                         return base.DoResolveMembers ();
353                 }
354
355                 public Variable CaptureScope (ScopeInfo child)
356                 {
357                         CheckMembersDefined ();
358                         Report.Debug (128, "CAPTURE SCOPE", this, GetType (), child, child.GetType ());
359                         if (child == this)
360                                 throw new InternalErrorException ();
361                         CapturedScope captured = (CapturedScope) captured_scopes [child];
362                         if (captured == null) {
363                                 captured = new CapturedScope (this, child);
364                                 captured_scopes.Add (child, captured);
365                         }
366                         return captured;
367                 }
368
369                 public Variable AddLocal (LocalInfo local)
370                 {
371                         Report.Debug (128, "CAPTURE LOCAL", this, local);
372                         Variable var = (Variable) locals [local];
373                         if (var == null) {
374                                 var = new CapturedLocal (this, local);
375                                 locals.Add (local, var);
376                                 local.IsCaptured = true;
377                         }
378                         return var;
379                 }
380
381                 public Variable GetCapturedVariable (LocalInfo local)
382                 {
383                         return (Variable) locals [local];
384                 }
385
386                 public bool HostsParameters {
387                         get { return captured_params != null; }
388                 }
389
390                 public Variable GetCapturedParameter (Parameter par)
391                 {
392                         if (captured_params != null)
393                                 return (Variable) captured_params [par];
394                         else
395                                 return null;
396                 }
397
398                 public Variable AddParameter (Parameter par, int idx)
399                 {
400                         if (captured_params == null)
401                                 captured_params = new Hashtable ();
402
403                         Variable var = (Variable) captured_params [par];
404                         if (var == null) {
405                                 var = new CapturedParameter (this, par, idx);
406                                 captured_params.Add (par, var);
407                                 par.IsCaptured = true;
408                         }
409
410                         return var;
411                 }
412
413                 public override void EmitType ()
414                 {
415                         SymbolWriter.DefineAnonymousScope (ID);
416                         foreach (CapturedLocal local in locals.Values)
417                                 local.EmitSymbolInfo ();
418
419                         if (captured_params != null) {
420                                 foreach (CapturedParameter param in captured_params.Values)
421                                         param.EmitSymbolInfo ();
422                         }
423
424                         foreach (CapturedScope scope in CapturedScopes) {
425                                 scope.EmitSymbolInfo ();
426                         }
427
428                         base.EmitType ();
429                 }
430
431                 protected string MakeFieldName (string local_name)
432                 {
433                         return "<" + ID + ":" + local_name + ">";
434                 }
435
436                 protected virtual ScopeInitializer CreateScopeInitializer ()
437                 {
438                         return new ScopeInitializer (this);
439                 }
440
441                 protected abstract class CapturedVariable : Variable
442                 {
443                         public readonly ScopeInfo Scope;
444                         public readonly string Name;
445
446                         public FieldExpr FieldInstance;
447                         protected Field field;
448
449                         protected CapturedVariable (ScopeInfo scope, string name)
450                         {
451                                 this.Scope = scope;
452                                 this.Name = name;
453                         }
454
455                         protected CapturedVariable (ScopeInfo scope, string name, Type type)
456                                 : this (scope, name)
457                         {
458                                 this.field = scope.CaptureVariable (
459                                         scope.MakeFieldName (name), scope.RootScope.InflateType (type));
460                         }
461
462                         public Field Field {
463                                 get { return field; }
464                         }
465
466                         public override Type Type {
467                                 get { return Field.MemberType; }
468                         }
469
470                         public override bool HasInstance {
471                                 get { return true; }
472                         }
473
474                         public override bool NeedsTemporary {
475                                 get { return true; }
476                         }
477
478                         protected FieldInfo GetField (EmitContext ec)
479                         {
480                                 if ((ec.CurrentBlock != null) &&
481                                     (ec.CurrentBlock.Toplevel != Scope.ScopeBlock.Toplevel))
482                                         return Field.FieldBuilder;
483                                 else
484                                         return FieldInstance.FieldInfo;
485                         }
486
487                         public abstract void EmitSymbolInfo ();
488
489                         public override void EmitInstance (EmitContext ec)
490                         {
491                                 if ((ec.CurrentAnonymousMethod != null) &&
492                                     (ec.CurrentAnonymousMethod.Scope == Scope)) {
493                                         ec.ig.Emit (OpCodes.Ldarg_0);
494                                         return;
495                                 }
496
497                                 Scope.EmitScopeInstance (ec);
498                         }
499
500                         public override void Emit (EmitContext ec)
501                         {
502                                 ec.ig.Emit (OpCodes.Ldfld, GetField (ec));
503                         }
504
505                         public override void EmitAssign (EmitContext ec)
506                         {
507                                 ec.ig.Emit (OpCodes.Stfld, GetField (ec));
508                         }
509
510                         public override void EmitAddressOf (EmitContext ec)
511                         {
512                                 ec.ig.Emit (OpCodes.Ldflda, GetField (ec));
513                         }
514                 }
515
516                 protected class CapturedParameter : CapturedVariable {
517                         public readonly Parameter Parameter;
518                         public readonly int Idx;
519
520                         public CapturedParameter (ScopeInfo scope, Parameter par, int idx)
521                                 : base (scope, par.Name, par.ParameterType)
522                         {
523                                 this.Parameter = par;
524                                 this.Idx = idx;
525                         }
526
527                         public override void EmitSymbolInfo ()
528                         {
529                                 SymbolWriter.DefineCapturedParameter (
530                                         Scope.ID, Parameter.Name, Field.Name);
531                         }
532
533                         public override string ToString ()
534                         {
535                                 return String.Format ("{0} ({1}:{2}:{3})", GetType (), Field,
536                                                       Parameter.Name, Idx);
537                         }
538                 }
539
540                 protected class CapturedLocal : CapturedVariable {
541                         public readonly LocalInfo Local;
542
543                         public CapturedLocal (ScopeInfo scope, LocalInfo local)
544                                 : base (scope, local.Name, local.VariableType)
545                         {
546                                 this.Local = local;
547                         }
548
549                         public override void EmitSymbolInfo ()
550                         {
551                                 SymbolWriter.DefineCapturedLocal (
552                                         Scope.ID, Local.Name, Field.Name);
553                         }
554
555                         public override string ToString ()
556                         {
557                                 return String.Format ("{0} ({1}:{2})", GetType (), Field,
558                                                       Local.Name);
559                         }
560                 }
561
562                 protected class CapturedThis : CapturedVariable {
563                         public CapturedThis (RootScopeInfo host)
564                                 : base (host, "<>THIS", host.ParentType)
565                         { }
566
567                         public override void EmitSymbolInfo ()
568                         {
569                                 SymbolWriter.DefineCapturedThis (Scope.ID, Field.Name);
570                         }
571                 }
572
573                 protected class CapturedScope : CapturedVariable {
574                         public readonly ScopeInfo ChildScope;
575
576                         public CapturedScope (ScopeInfo root, ScopeInfo child)
577                                 : base (root, "scope" + child.ID)
578                         {
579                                 this.ChildScope = child;
580                         }
581
582                         public override void EmitSymbolInfo ()
583                         {
584                                 SymbolWriter.DefineCapturedScope (Scope.ID, ChildScope.ID, Field.Name);
585                         }
586
587                         public bool DefineMembers ()
588                         {
589                                 Type type = ChildScope.IsGeneric ?
590                                         ChildScope.CurrentType : ChildScope.TypeBuilder;
591                                 Report.Debug (128, "CAPTURED SCOPE DEFINE MEMBERS", this, Scope,
592                                               ChildScope, Name, type);
593                                 if (type == null)
594                                         throw new InternalErrorException ();
595                                 field = Scope.CaptureVariable (
596                                         Scope.MakeFieldName (Name), Scope.InflateType (type));
597                                 return true;
598                         }
599
600                         public override string ToString ()
601                         {
602                                 return String.Format ("CapturedScope ({1} captured in {0})",
603                                                       Scope, ChildScope);
604                         }
605                 }
606
607                 static void DoPath (StringBuilder sb, ScopeInfo start)
608                 {
609                         sb.Append ((start.ID).ToString ());
610                 }
611                 
612                 public override string ToString ()
613                 {
614                         StringBuilder sb = new StringBuilder ();
615                         
616                         sb.Append ("{");
617                         DoPath (sb, this);
618                         sb.Append ("}");
619
620                         return sb.ToString ();
621                 }
622
623                 protected class ScopeInitializer : ExpressionStatement
624                 {
625                         ScopeInfo scope;
626                         CapturedVariable captured_scope;
627                         LocalBuilder scope_instance;
628                         ConstructorInfo scope_ctor;
629
630                         bool initialized;
631
632                         public ScopeInitializer (ScopeInfo scope)
633                         {
634                                 this.scope = scope;
635                                 this.loc = scope.Location;
636                                 eclass = ExprClass.Value;
637                         }
638
639                         public ScopeInfo Scope {
640                                 get { return scope; }
641                         }
642
643                         public override Expression DoResolve (EmitContext ec)
644                         {
645                                 if (scope_ctor != null)
646                                         return this;
647
648                                 Report.Debug (64, "RESOLVE SCOPE INITIALIZER BASE", this, Scope,
649                                               ec, ec.CurrentBlock);
650
651                                 type = Scope.GetScopeType (ec);
652                                 if (type == null)
653                                         throw new InternalErrorException ();
654
655                                 if (!DoResolveInternal (ec))
656                                         throw new InternalErrorException ();
657
658                                 return this;
659                         }
660
661                         protected virtual bool DoResolveInternal (EmitContext ec)
662                         {
663                                 MethodGroupExpr mg = (MethodGroupExpr) MemberLookupFinal (
664                                         ec, ec.ContainerType, type, ".ctor", MemberTypes.Constructor,
665                                         AllBindingFlags | BindingFlags.DeclaredOnly, loc);
666                                 if (mg == null)
667                                         throw new InternalErrorException ();
668
669                                 scope_ctor = (ConstructorInfo) mg.Methods [0];
670
671                                 Report.Debug (128, "RESOLVE THE INIT", this, Scope, Scope.RootScope,
672                                               Scope.RootScope.GetType ());
673
674                                 ScopeInfo host = Scope.RootScope;
675                                 if ((Scope != host) && (Scope.RootScope is IteratorHost)) {
676                                         captured_scope = host.GetCapturedScope (Scope);
677                                         Type root = host.GetScopeType (ec);
678                                         FieldExpr fe = (FieldExpr) Expression.MemberLookup (
679                                                 type, root, captured_scope.Field.Name, loc);
680                                         if (fe == null)
681                                                 throw new InternalErrorException ();
682
683                                         fe.InstanceExpression = this;
684                                         captured_scope.FieldInstance = fe;
685
686                                         Report.Debug (128, "RESOLVE THE INIT #1", this,
687                                                       captured_scope, fe);
688                                 } else {
689                                         scope_instance = ec.ig.DeclareLocal (type);
690                                         if (!Scope.RootScope.IsIterator)
691                                                 SymbolWriter.DefineScopeVariable (Scope.ID, scope_instance);
692                                 }
693
694                                 foreach (CapturedLocal local in Scope.locals.Values) {
695                                         FieldExpr fe = (FieldExpr) Expression.MemberLookup (
696                                                 ec.ContainerType, type, local.Field.Name, loc);
697                                         Report.Debug (64, "RESOLVE SCOPE INITIALIZER #2", this, Scope,
698                                                       Scope, ec, ec.ContainerType, type,
699                                                       local.Field, local.Field.Name, loc, fe);
700                                         if (fe == null)
701                                                 throw new InternalErrorException ();
702
703                                         fe.InstanceExpression = this;
704                                         local.FieldInstance = fe;
705                                 }
706
707                                 if (Scope.HostsParameters) {
708                                         foreach (CapturedParameter cp in Scope.captured_params.Values) {
709                                                 FieldExpr fe = (FieldExpr) Expression.MemberLookup (
710                                                         ec.ContainerType, type, cp.Field.Name, loc);
711                                                 if (fe == null)
712                                                         throw new InternalErrorException ();
713
714                                                 fe.InstanceExpression = this;
715                                                 cp.FieldInstance = fe;
716                                         }
717                                 }
718
719                                 foreach (CapturedScope scope in Scope.CapturedScopes) {
720                                         FieldExpr fe = (FieldExpr) Expression.MemberLookup (
721                                                 ec.ContainerType, type, scope.Field.Name, loc);
722                                         Report.Debug (64, "RESOLVE SCOPE INITIALIZER #3", this, Scope,
723                                                       scope, ec, ec.ContainerType, type,
724                                                       scope.Field, scope.Field.Name, loc, fe);
725                                         if (fe == null)
726                                                 throw new InternalErrorException ();
727
728                                         fe.InstanceExpression = this;
729                                         scope.FieldInstance = fe;
730                                 }
731
732                                 return true;
733                         }
734
735                         protected virtual void EmitParameterReference (EmitContext ec,
736                                                                        CapturedParameter cp)
737                         {
738                                 int extra = ec.MethodIsStatic ? 0 : 1;
739                                 ParameterReference.EmitLdArg (ec.ig, cp.Idx + extra);
740                         }
741
742                         static int next_id;
743                         int id = ++next_id;
744
745                         protected virtual void DoEmit (EmitContext ec)
746                         {
747                                 if ((ec.CurrentBlock != null) &&
748                                     (ec.CurrentBlock.Toplevel != Scope.ScopeBlock.Toplevel)) {
749                                         ec.ig.Emit (OpCodes.Ldarg_0);
750
751                                         if (ec.CurrentAnonymousMethod != null) {
752                                                 ScopeInfo host = ec.CurrentAnonymousMethod.Scope;
753                                                 Variable captured = host.GetCapturedScope (scope);
754                                                 Report.Debug (128, "EMIT SCOPE INSTANCE #2",
755                                                               ec.CurrentAnonymousMethod, host,
756                                                               scope, captured);
757                                                 if (captured != null)
758                                                         captured.Emit (ec);
759                                         }
760                                 } else if (scope_instance != null)
761                                         ec.ig.Emit (OpCodes.Ldloc, scope_instance);
762                                 else {
763                                         Report.Debug (128, "DO EMIT", this, Scope, ec,
764                                                       scope_instance, captured_scope);
765                                         captured_scope.EmitInstance (ec);
766                                         captured_scope.Emit (ec);
767                                 }
768                         }
769
770                         protected void DoEmitInstance (EmitContext ec)
771                         {
772                                 Report.Debug (128, "DO EMIT INSTANCE", this, Scope, ec,
773                                               scope_instance, captured_scope);
774
775                                 if (scope_instance != null)
776                                         ec.ig.Emit (OpCodes.Ldloc, scope_instance);
777                                 else
778                                         captured_scope.EmitInstance (ec);
779                         }
780
781                         protected virtual void EmitScopeConstructor (EmitContext ec)
782                         {
783                                 ec.ig.Emit (OpCodes.Newobj, scope_ctor);
784                         }
785
786                         public override void Emit (EmitContext ec)
787                         {
788                                 if (!initialized)
789                                         throw new InternalErrorException (
790                                                 "Scope {0} not initialized yet", scope);
791
792                                 DoEmit (ec);
793                         }
794
795                         public override void EmitStatement (EmitContext ec)
796                         {
797                                 if (initialized)
798                                         return;
799
800                                 DoEmitStatement (ec);
801                                 initialized = true;
802                         }
803
804                         protected virtual void DoEmitStatement (EmitContext ec)
805                         {
806                                 Report.Debug (128, "EMIT SCOPE INITIALIZER STATEMENT", this, id,
807                                               Scope, scope_instance, ec);
808
809                                 ec.ig.Emit (OpCodes.Nop);
810                                 ec.ig.Emit (OpCodes.Ldc_I4, id);
811                                 ec.ig.Emit (OpCodes.Pop);
812                                 ec.ig.Emit (OpCodes.Nop);
813
814                                 if (scope_instance == null)
815                                         ec.ig.Emit (OpCodes.Ldarg_0);
816                                 EmitScopeConstructor (ec);
817                                 if (scope_instance != null)
818                                         ec.ig.Emit (OpCodes.Stloc, scope_instance);
819                                 else
820                                         captured_scope.EmitAssign (ec);
821
822                                 if (Scope.HostsParameters) {
823                                         foreach (CapturedParameter cp in Scope.captured_params.Values) {
824                                                 Report.Debug (128, "EMIT SCOPE INIT #6", this,
825                                                               ec, ec.IsStatic, Scope, cp, cp.Field.Name);
826                                                 DoEmitInstance (ec);
827                                                 EmitParameterReference (ec, cp);
828                                                 ec.ig.Emit (OpCodes.Stfld, cp.FieldInstance.FieldInfo);
829                                         }
830                                 }
831
832                                 if (Scope is IteratorHost)
833                                         return;
834
835                                 foreach (CapturedScope scope in Scope.CapturedScopes) {
836                                         ScopeInfo child = scope.ChildScope;
837
838                                         Report.Debug (128, "EMIT SCOPE INIT #5", this, Scope,
839                                                       scope.Scope, scope.ChildScope);
840
841                                         ExpressionStatement init = child.GetScopeInitializer (ec);
842                                         init.EmitStatement (ec);
843
844                                         DoEmit (ec);
845                                         scope.ChildScope.EmitScopeInstance (ec);
846                                         scope.EmitAssign (ec);
847                                 }
848                         }
849                 }
850         }
851
852         public class RootScopeInfo : ScopeInfo
853         {
854                 public RootScopeInfo (ToplevelBlock toplevel, DeclSpace parent,
855                                       GenericMethod generic, Location loc)
856                         : base (toplevel, parent, generic, loc)
857                 {
858                         scopes = new ArrayList ();
859                 }
860
861                 TypeExpr parent_type;
862                 CapturedVariableField parent_link;
863                 CapturedThis this_variable;
864                 protected ArrayList scopes;
865
866                 public virtual bool IsIterator {
867                         get { return false; }
868                 }
869
870                 public RootScopeInfo ParentHost {
871                         get { return Parent.PartialContainer as RootScopeInfo; }
872                 }
873
874                 public Type ParentType {
875                         get { return parent_type.Type; }
876                 }
877
878                 public Field ParentLink {
879                         get { return parent_link; }
880                 }
881
882                 protected CapturedThis THIS {
883                         get { return this_variable; }
884                 }
885
886                 public Variable CaptureThis ()
887                 {
888                         if (ParentHost != null)
889                                 return ParentHost.CaptureThis ();
890
891                         CheckMembersDefined ();
892                         if (this_variable == null)
893                                 this_variable = new CapturedThis (this);
894                         return this_variable;
895                 }
896
897                 public void AddScope (ScopeInfo scope)
898                 {
899                         scopes.Add (scope);
900                 }
901
902                 bool linked;
903                 public void LinkScopes ()
904                 {
905                         Report.Debug (128, "LINK SCOPES", this, linked, scopes);
906
907                         if (linked)
908                                 return;
909
910                         linked = true;
911                         if (ParentHost != null)
912                                 ParentHost.LinkScopes ();
913
914                         foreach (ScopeInfo si in scopes) {
915                                 if (!si.Define ())
916                                         throw new InternalErrorException ();
917                                 if (si.DefineType () == null)
918                                         throw new InternalErrorException ();
919                                 if (!si.ResolveType ())
920                                         throw new InternalErrorException ();
921                         }
922
923                         foreach (ScopeInfo si in scopes) {
924                                 if (!si.ResolveMembers ())
925                                         throw new InternalErrorException ();
926                                 if (!si.DefineMembers ())
927                                         throw new InternalErrorException ();
928                         }
929                 }
930
931                 protected override ScopeInitializer CreateScopeInitializer ()
932                 {
933                         return new RootScopeInitializer (this);
934                 }
935
936                 protected override bool DefineNestedTypes ()
937                 {
938                         if (Parent.IsGeneric) {
939                                 parent_type = new ConstructedType (
940                                         Parent.TypeBuilder, Parent.TypeParameters, Location);
941                                 parent_type = parent_type.ResolveAsTypeTerminal (this, false);
942                                 if ((parent_type == null) || (parent_type.Type == null))
943                                         return false;
944                         } else {
945                                 parent_type = new TypeExpression (Parent.TypeBuilder, Location);
946                         }
947
948                         CompilerGeneratedClass parent = Parent.PartialContainer as CompilerGeneratedClass;
949                         if (parent != null)
950                                 parent_link = new CapturedVariableField (this, "<>parent", parent_type);
951
952                         return base.DefineNestedTypes ();
953                 }
954
955                 protected override bool DoDefineMembers ()
956                 {
957                         ArrayList args = new ArrayList ();
958                         if (this is IteratorHost)
959                                 args.Add (new Parameter (
960                                         TypeManager.int32_type, "$PC", Parameter.Modifier.NONE,
961                                         null, Location));
962
963                         Field pfield;
964                         if (Parent is CompilerGeneratedClass)
965                                 pfield = parent_link;
966                         else
967                                 pfield = this_variable !=  null ? this_variable.Field : null;
968                         if (pfield != null)
969                                 args.Add (new Parameter (
970                                         pfield.MemberType, "parent", Parameter.Modifier.NONE,
971                                         null, Location));
972
973                         Parameter[] ctor_params = new Parameter [args.Count];
974                         args.CopyTo (ctor_params, 0);
975                         Constructor ctor = new Constructor (
976                                 this, MemberName.Name, Modifiers.PUBLIC,
977                                 new Parameters (ctor_params),
978                                 new GeneratedBaseInitializer (Location),
979                                 Location);
980                         AddConstructor (ctor);
981
982                         ctor.Block = new ToplevelBlock (null, Location);
983                         ctor.Block.AddStatement (new TheCtor (this));
984
985                         return base.DoDefineMembers ();
986                 }
987
988                 protected virtual void EmitScopeConstructor (EmitContext ec)
989                 {
990                         int pos = (this is IteratorHost) ? 2 : 1;
991
992                         Field pfield;
993                         if (Parent is CompilerGeneratedClass)
994                                 pfield = parent_link;
995                         else
996                                 pfield = this_variable !=  null ? this_variable.Field : null;
997
998                         if (pfield != null) {
999                                 ec.ig.Emit (OpCodes.Ldarg_0);
1000                                 ec.ig.Emit (OpCodes.Ldarg, pos);
1001                                 ec.ig.Emit (OpCodes.Stfld, pfield.FieldBuilder);
1002                                 pos++;
1003                         }
1004                 }
1005
1006                 public override void EmitType ()
1007                 {
1008                         base.EmitType ();
1009                         if (THIS != null)
1010                                 THIS.EmitSymbolInfo ();
1011                 }
1012
1013                 protected class TheCtor : Statement
1014                 {
1015                         RootScopeInfo host;
1016
1017                         public TheCtor (RootScopeInfo host)
1018                         {
1019                                 this.host = host;
1020                         }
1021
1022                         public override bool Resolve (EmitContext ec)
1023                         {
1024                                 return true;
1025                         }
1026
1027                         protected override void DoEmit (EmitContext ec)
1028                         {
1029                                 host.EmitScopeConstructor (ec);
1030                         }
1031                 }
1032
1033                 protected class RootScopeInitializer : ScopeInitializer
1034                 {
1035                         RootScopeInfo host;
1036
1037                         public RootScopeInitializer (RootScopeInfo host)
1038                                 : base (host)
1039                         {
1040                                 this.host = host;
1041                         }
1042
1043                         public RootScopeInfo Host {
1044                                 get { return host; }
1045                         }
1046
1047                         protected override bool DoResolveInternal (EmitContext ec)
1048                         {
1049                                 Report.Debug (64, "RESOLVE ANONYMOUS METHOD HOST INITIALIZER",
1050                                               this, Host, Host.ParentType, loc);
1051
1052                                 if (Host.THIS != null) {
1053                                         FieldExpr fe = (FieldExpr) Expression.MemberLookup (
1054                                                 ec.ContainerType, type, Host.THIS.Field.Name, loc);
1055                                         if (fe == null)
1056                                                 throw new InternalErrorException ();
1057
1058                                         fe.InstanceExpression = this;
1059                                         Host.THIS.FieldInstance = fe;
1060                                 }
1061
1062                                 return base.DoResolveInternal (ec);
1063                         }
1064
1065                         protected virtual bool IsGetEnumerator {
1066                                 get { return false; }
1067                         }
1068
1069                         protected override void EmitScopeConstructor (EmitContext ec)
1070                         {
1071                                 if (host.THIS != null) {
1072                                         ec.ig.Emit (OpCodes.Ldarg_0);
1073                                         if (IsGetEnumerator)
1074                                                 ec.ig.Emit (OpCodes.Ldfld, host.THIS.Field.FieldBuilder);
1075                                         else if (host.THIS.Type.IsValueType)
1076                                                 Expression.LoadFromPtr (ec.ig, host.THIS.Type);
1077                                 } else if (host.ParentLink != null)
1078                                         ec.ig.Emit (OpCodes.Ldarg_0);
1079
1080                                 base.EmitScopeConstructor (ec);
1081                         }
1082                 }
1083
1084         }
1085
1086         public interface IAnonymousContainer
1087         {
1088                 Block Container {
1089                         get;
1090                 }
1091
1092                 GenericMethod GenericMethod {
1093                         get;
1094                 }
1095
1096                 RootScopeInfo RootScope {
1097                         get;
1098                 }
1099
1100                 bool IsIterator {
1101                         get;
1102                 }
1103         }
1104
1105         public interface IAnonymousHost
1106         {
1107                 //
1108                 // Invoked if a yield statement is found in the body
1109                 //
1110                 void SetYields ();
1111
1112                 //
1113                 // Invoked if an anonymous method is found in the body
1114                 //
1115                 void AddAnonymousMethod (AnonymousMethodExpression anonymous);
1116         }
1117
1118         public class AnonymousMethodExpression : Expression, IAnonymousContainer, IAnonymousHost
1119         {
1120                 public readonly AnonymousMethodExpression Parent;
1121                 public readonly TypeContainer Host;
1122                 public readonly Parameters Parameters;
1123
1124                 public ToplevelBlock Block;
1125
1126                 protected Block container;
1127                 protected readonly GenericMethod generic;
1128
1129                 public Block Container {
1130                         get { return container; }
1131                 }
1132
1133                 public GenericMethod GenericMethod {
1134                         get { return generic; }
1135                 }
1136
1137                 public RootScopeInfo RootScope {
1138                         get { return root_scope; }
1139                 }
1140
1141                 public AnonymousMethodExpression (AnonymousMethodExpression parent,
1142                                                   GenericMethod generic, TypeContainer host,
1143                                                   Parameters parameters, Block container,
1144                                                   Location loc)
1145                 {
1146                         this.Parent = parent;
1147                         this.generic = parent != null ? null : generic;
1148                         this.Host = host;
1149                         this.Parameters = parameters;
1150                         this.container = container;
1151                         this.loc = loc;
1152
1153                         Report.Debug (64, "NEW ANONYMOUS METHOD EXPRESSION", this, parent, host,
1154                                       container, loc);
1155
1156                         if (parent != null)
1157                                 parent.AddAnonymousMethod (this);
1158                 }
1159
1160                 ArrayList children;
1161                 RootScopeInfo root_scope;
1162
1163                 static int next_index;
1164
1165                 void IAnonymousHost.SetYields ()
1166                 {
1167                         throw new InvalidOperationException ();
1168                 }
1169
1170                 public void AddAnonymousMethod (AnonymousMethodExpression anonymous)
1171                 {
1172                         if (children == null)
1173                                 children = new ArrayList ();
1174                         children.Add (anonymous);
1175                 }
1176
1177                 public bool CreateAnonymousHelpers ()
1178                 {
1179                         // FIXME: this polutes expression trees implementation
1180
1181                         Report.Debug (64, "ANONYMOUS METHOD EXPRESSION CREATE ROOT SCOPE",
1182                                       this, Host, container, loc);
1183
1184                         if (container != null)
1185                                 root_scope = container.Toplevel.CreateRootScope (Host);
1186
1187                         if (children != null) {
1188                                 foreach (AnonymousMethodExpression child in children) {
1189                                         if (!child.CreateAnonymousHelpers ())
1190                                                 return false;
1191                                 }
1192                         }
1193
1194                         return true;
1195                 }
1196
1197                 public override string ExprClassName {
1198                         get {
1199                                 return "anonymous method";
1200                         }
1201                 }
1202
1203                 public virtual bool HasExplicitParameters {
1204                         get {
1205                                 return true;
1206                         }
1207                 }
1208
1209                 //
1210                 // Returns true if the body of lambda expression can be implicitly
1211                 // converted to the delegate of type `delegate_type'
1212                 //
1213                 public bool ImplicitStandardConversionExists (Type delegate_type)
1214                 {
1215                         EmitContext ec = EmitContext.TempEc;
1216                         using (ec.Set (EmitContext.Flags.ProbingMode)) {
1217                                 return Compatible (ec, delegate_type) != null;
1218                         }
1219                 }
1220
1221                 protected Type CompatibleChecks (EmitContext ec, Type delegate_type)
1222                 {
1223                         if (!ec.IsAnonymousMethodAllowed) {
1224                                 Report.Error (1706, loc, "Anonymous methods and lambda expressions cannot be used in the current context");
1225                                 return null;
1226                         }
1227                         
1228                         if (TypeManager.IsDelegateType (delegate_type))
1229                                 return delegate_type;
1230
1231 #if GMCS_SOURCE
1232                         if (TypeManager.DropGenericTypeArguments (delegate_type) == TypeManager.expression_type) {
1233                                 delegate_type = TypeManager.GetTypeArguments (delegate_type) [0];
1234                                 if (TypeManager.IsDelegateType (delegate_type))
1235                                         return delegate_type;
1236
1237                                 Report.Error (835, loc, "Cannot convert `{0}' to an expression tree of non-delegate type `{1}'",
1238                                         GetSignatureForError (), TypeManager.CSharpName (delegate_type));
1239                                 return null;
1240                         }
1241 #endif
1242
1243                         Report.Error (1660, loc, "Cannot convert `{0}' to non-delegate type `{1}'",
1244                                       GetSignatureForError (), TypeManager.CSharpName (delegate_type));
1245                         return null;
1246                 }
1247
1248                 protected bool VerifyExplicitParameters (Type delegate_type, ParameterData parameters, bool ignore_error)
1249                 {
1250                         if (VerifyParameterCompatibility (delegate_type, parameters, ignore_error))
1251                                 return true;
1252
1253                         if (!ignore_error)
1254                                 Report.Error (1661, loc,
1255                                         "Cannot convert `{0}' to delegate type `{1}' since there is a parameter mismatch",
1256                                         GetSignatureForError (), TypeManager.CSharpName (delegate_type));
1257
1258                         return false;
1259                 }
1260
1261                 protected bool VerifyParameterCompatibility (Type delegate_type, ParameterData invoke_pd, bool ignore_errors)
1262                 {
1263                         if (Parameters.Count != invoke_pd.Count) {
1264                                 if (ignore_errors)
1265                                         return false;
1266                                 
1267                                 Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments",
1268                                               TypeManager.CSharpName (delegate_type), Parameters.Count.ToString ());
1269                                 return false;
1270                         }
1271                         
1272                         if (!HasExplicitParameters)
1273                                 return true;                    
1274
1275                         bool error = false;
1276                         for (int i = 0; i < Parameters.Count; ++i) {
1277                                 Parameter.Modifier p_mod = invoke_pd.ParameterModifier (i);
1278                                 if (Parameters.ParameterModifier (i) != p_mod && p_mod != Parameter.Modifier.PARAMS) {
1279                                         if (ignore_errors)
1280                                                 return false;
1281                                         
1282                                         if (p_mod == Parameter.Modifier.NONE)
1283                                                 Report.Error (1677, loc, "Parameter `{0}' should not be declared with the `{1}' keyword",
1284                                                               (i + 1).ToString (), Parameter.GetModifierSignature (Parameters.ParameterModifier (i)));
1285                                         else
1286                                                 Report.Error (1676, loc, "Parameter `{0}' must be declared with the `{1}' keyword",
1287                                                               (i+1).ToString (), Parameter.GetModifierSignature (p_mod));
1288                                         error = true;
1289                                         continue;
1290                                 }
1291
1292                                 Type type = invoke_pd.Types [i];
1293                                 
1294                                 // We assume that generic parameters are always inflated
1295                                 if (TypeManager.IsGenericParameter (type))
1296                                         continue;
1297                                 
1298                                 if (TypeManager.HasElementType (type) && TypeManager.IsGenericParameter (TypeManager.GetElementType (type)))
1299                                         continue;
1300                                 
1301                                 if (invoke_pd.ParameterType (i) != Parameters.ParameterType (i)) {
1302                                         if (ignore_errors)
1303                                                 return false;
1304                                         
1305                                         Report.Error (1678, loc, "Parameter `{0}' is declared as type `{1}' but should be `{2}'",
1306                                                       (i+1).ToString (),
1307                                                       TypeManager.CSharpName (Parameters.ParameterType (i)),
1308                                                       TypeManager.CSharpName (invoke_pd.ParameterType (i)));
1309                                         error = true;
1310                                 }
1311                         }
1312
1313                         return !error;
1314                 }
1315
1316                 //
1317                 // Infers type arguments based on explicit arguments
1318                 //
1319                 public bool ExplicitTypeInference (TypeInferenceContext type_inference, Type delegate_type)
1320                 {
1321                         if (!HasExplicitParameters)
1322                                 return false;
1323
1324                         if (!TypeManager.IsDelegateType (delegate_type)) {
1325 #if GMCS_SOURCE
1326                                 if (TypeManager.DropGenericTypeArguments (delegate_type) != TypeManager.expression_type)
1327                                         return false;
1328
1329                                 delegate_type = delegate_type.GetGenericArguments () [0];
1330                                 if (!TypeManager.IsDelegateType (delegate_type))
1331                                         return false;
1332 #else
1333                                 return false;
1334 #endif
1335                         }
1336                         
1337                         ParameterData d_params = TypeManager.GetDelegateParameters (delegate_type);
1338                         if (d_params.Count != Parameters.Count)
1339                                 return false;
1340
1341                         for (int i = 0; i < Parameters.Count; ++i) {
1342                                 Type itype = d_params.Types [i];
1343                                 if (!TypeManager.IsGenericParameter (itype)) {
1344                                         if (!TypeManager.HasElementType (itype))
1345                                                 continue;
1346                                         
1347                                         if (!TypeManager.IsGenericParameter (itype.GetElementType ()))
1348                                             continue;
1349                                 }
1350                                 type_inference.ExactInference (Parameters.FixedParameters[i].ParameterType, itype);
1351                         }
1352                         return true;
1353                 }
1354
1355                 public Type InferReturnType (EmitContext ec, TypeInferenceContext tic, Type delegate_type)
1356                 {
1357                         AnonymousMethod am;
1358                         using (ec.Set (EmitContext.Flags.ProbingMode | EmitContext.Flags.InferReturnType)) {
1359                                 am = CompatibleMethod (ec, tic, GetType (), delegate_type);
1360                         }
1361                         
1362                         if (am == null)
1363                                 return null;
1364
1365                         if (am.ReturnType == TypeManager.null_type)
1366                                 am.ReturnType = null;
1367
1368                         return am.ReturnType;
1369                 }
1370
1371                 //
1372                 // Returns AnonymousMethod container if this anonymous method
1373                 // expression can be implicitly converted to the delegate type `delegate_type'
1374                 //
1375                 public Expression Compatible (EmitContext ec, Type type)
1376                 {
1377                         Type delegate_type = CompatibleChecks (ec, type);
1378                         if (delegate_type == null)
1379                                 return null;
1380
1381                         //
1382                         // At this point its the first time we know the return type that is 
1383                         // needed for the anonymous method.  We create the method here.
1384                         //
1385
1386                         MethodInfo invoke_mb = Delegate.GetInvokeMethod (
1387                                 ec.ContainerType, delegate_type);
1388                         Type return_type = TypeManager.TypeToCoreType (invoke_mb.ReturnType);
1389
1390 #if MS_COMPATIBLE
1391                         Type[] g_args = delegate_type.GetGenericArguments ();
1392                         if (return_type.IsGenericParameter)
1393                                 return_type = g_args [return_type.GenericParameterPosition];
1394 #endif
1395
1396                         //
1397                         // Second: the return type of the delegate must be compatible with 
1398                         // the anonymous type.   Instead of doing a pass to examine the block
1399                         // we satisfy the rule by setting the return type on the EmitContext
1400                         // to be the delegate type return type.
1401                         //
1402
1403                         Report.Debug (64, "COMPATIBLE", this, Parent, GenericMethod, Host,
1404                                       Container, Block, return_type, delegate_type,
1405                                       TypeManager.IsGenericType (delegate_type), loc);
1406
1407                         try {
1408                                 AnonymousMethod am = CompatibleMethod (ec, null, return_type, delegate_type);
1409                                 if (am != null && delegate_type != type)
1410                                         return CreateExpressionTree (ec, delegate_type);
1411
1412                                 return am;
1413                         } catch (Exception e) {
1414                                 throw new InternalErrorException (e, loc);
1415                         }
1416                 }
1417
1418                 protected virtual Expression CreateExpressionTree (EmitContext ec, Type delegate_type)
1419                 {
1420                         Report.Error (1946, loc, "An anonymous method cannot be converted to an expression tree");
1421                         return null;
1422                 }
1423
1424                 protected virtual Parameters ResolveParameters (EmitContext ec, TypeInferenceContext tic, Type delegate_type)
1425                 {
1426                         ParameterData delegate_parameters = TypeManager.GetDelegateParameters (delegate_type);
1427
1428                         if (Parameters == null) {
1429                                 //
1430                                 // We provide a set of inaccessible parameters
1431                                 //
1432                                 Parameter[] fixedpars = new Parameter[delegate_parameters.Count];
1433
1434                                 for (int i = 0; i < delegate_parameters.Count; i++) {
1435                                         Parameter.Modifier i_mod = delegate_parameters.ParameterModifier (i);
1436                                         if ((i_mod & Parameter.Modifier.OUTMASK) != 0) {
1437                                                 Report.Error (1688, loc, "Cannot convert anonymous " +
1438                                                                   "method block without a parameter list " +
1439                                                                   "to delegate type `{0}' because it has " +
1440                                                                   "one or more `out' parameters.",
1441                                                                   TypeManager.CSharpName (delegate_type));
1442                                                 return null;
1443                                         }
1444                                         fixedpars[i] = new Parameter (
1445                                                 delegate_parameters.ParameterType (i), "+" + (++next_index),
1446                                                 delegate_parameters.ParameterModifier (i), null, loc);
1447                                 }
1448
1449                                 return Parameters.CreateFullyResolved (fixedpars, delegate_parameters.Types);
1450                         }
1451
1452                         if (!VerifyExplicitParameters (delegate_type, delegate_parameters, ec.IsInProbingMode)) {
1453                                 return null;
1454                         }
1455
1456                         return Parameters;
1457                 }
1458
1459                 public override Expression DoResolve (EmitContext ec)
1460                 {
1461                         //
1462                         // Set class type, set type
1463                         //
1464
1465                         eclass = ExprClass.Value;
1466
1467                         //
1468                         // This hack means `The type is not accessible
1469                         // anywhere', we depend on special conversion
1470                         // rules.
1471                         // 
1472                         type = TypeManager.anonymous_method_type;
1473
1474                         if ((Parameters != null) && !Parameters.Resolve (ec))
1475                                 return null;
1476
1477                         return this;
1478                 }
1479
1480                 public override void Emit (EmitContext ec)
1481                 {
1482                         // nothing, as we only exist to not do anything.
1483                 }
1484
1485                 public override string GetSignatureForError ()
1486                 {
1487                         return ExprClassName;
1488                 }
1489
1490                 public bool IsIterator {
1491                         get { return false; }
1492                 }
1493
1494                 protected AnonymousMethod CompatibleMethod (EmitContext ec, TypeInferenceContext tic, Type return_type, Type delegate_type)
1495                 {
1496                         Parameters p = ResolveParameters (ec, tic, delegate_type);
1497                         if (p == null)
1498                                 return null;
1499
1500                         ToplevelBlock b = ec.IsInProbingMode ? (ToplevelBlock) Block.PerformClone () : Block;
1501
1502                         AnonymousMethod anonymous = CompatibleMethodFactory (return_type, delegate_type, p, b);
1503                         if (!anonymous.Compatible (ec))
1504                                 return null;
1505
1506                         return anonymous;
1507                 }
1508
1509                 protected virtual AnonymousMethod CompatibleMethodFactory (Type return_type, Type delegate_type, Parameters p, ToplevelBlock b)
1510                 {
1511                         return new AnonymousMethod (RootScope, Host,
1512                                 GenericMethod, p, Container, b, return_type,
1513                                 delegate_type, loc);
1514                 }
1515
1516                 protected override void CloneTo (CloneContext clonectx, Expression t)
1517                 {
1518                         AnonymousMethodExpression target = (AnonymousMethodExpression) t;
1519
1520                         target.Block = (ToplevelBlock) clonectx.LookupBlock (Block);
1521                         target.container = clonectx.LookupBlock (Block);
1522                 }
1523         }
1524
1525         public abstract class AnonymousContainer : Expression, IAnonymousContainer
1526         {
1527                 public Parameters Parameters;
1528
1529                 //
1530                 // The block that makes up the body for the anonymous mehtod
1531                 //
1532                 public readonly ToplevelBlock Block;
1533
1534                 public readonly int ModFlags;
1535                 public Type ReturnType;
1536                 public readonly DeclSpace Host;
1537
1538                 //
1539                 // The implicit method we create
1540                 //
1541                 protected Method method;
1542                 protected EmitContext aec;
1543
1544                 // The emit context for the anonymous method
1545                 protected bool unreachable;
1546                 protected readonly Block container;
1547                 protected readonly GenericMethod generic;
1548
1549                 protected AnonymousContainer (DeclSpace host,
1550                                               GenericMethod generic, Parameters parameters,
1551                                               Block container, ToplevelBlock block,
1552                                               Type return_type, int mod, Location loc)
1553                 {
1554                         this.ReturnType = return_type;
1555                         this.ModFlags = mod | Modifiers.COMPILER_GENERATED;
1556                         this.Host = host;
1557
1558                         this.container = container;
1559                         this.generic = generic;
1560                         this.Parameters = parameters;
1561                         this.Block = block;
1562                         this.loc = loc;
1563
1564                         block.AnonymousContainer = this;
1565                 }
1566
1567                 public Method Method {
1568                         get { return method; }
1569                 }
1570
1571                 public abstract string ContainerType {
1572                         get; 
1573                 }
1574
1575                 public abstract RootScopeInfo RootScope {
1576                         get;
1577                 }
1578
1579                 public abstract ScopeInfo Scope {
1580                         get;
1581                 }
1582
1583                 public bool Compatible (EmitContext ec)
1584                 {
1585                         // REFACTOR: The method should be refactor, many of the
1586                         // hacks can be handled in better way
1587
1588                         Report.Debug (64, "RESOLVE ANONYMOUS METHOD", this, Location, ec,
1589                                       RootScope, Parameters, ec.IsStatic);
1590
1591                         if (ReturnType != null) {
1592                                 TypeExpr return_type_expr;
1593                                 if (RootScope != null)
1594                                         return_type_expr = RootScope.InflateType (ReturnType);
1595                                 else
1596                                         return_type_expr = new TypeExpression (ReturnType, Location);
1597                                 return_type_expr = return_type_expr.ResolveAsTypeTerminal (ec, false);
1598                                 if ((return_type_expr == null) || (return_type_expr.Type == null))
1599                                         return false;
1600                                 ReturnType = return_type_expr.Type;
1601                         }
1602
1603                         // Linq type inference is done differently
1604                         if (RootScope != null && RootContext.Version != LanguageVersion.LINQ)
1605                                 Parameters = RootScope.InflateParameters (Parameters);
1606
1607                         aec = new EmitContext (
1608                                 ec.ResolveContext, ec.TypeContainer,
1609                                 RootScope != null ? RootScope : Host, Location, null, ReturnType,
1610                                 /* REVIEW */ (ec.InIterator ? Modifiers.METHOD_YIELDS : 0) |
1611                                 (ec.InUnsafe ? Modifiers.UNSAFE : 0), /* No constructor */ false);
1612
1613                         aec.CurrentAnonymousMethod = this;
1614                         aec.IsStatic = ec.IsStatic;
1615                         
1616                         //
1617                         // HACK: Overwrite parent declaration container to currently resolved.
1618                         // It's required for an anonymous container inside partial class.
1619                         //
1620                         if (RootScope != null)
1621                                 aec.DeclContainer.Parent = ec.TypeContainer;
1622
1623                         IDisposable aec_dispose = null;
1624                         EmitContext.Flags flags = 0;
1625                         if (ec.InferReturnType)
1626                                 flags |= EmitContext.Flags.InferReturnType;
1627                         
1628                         if (ec.IsInProbingMode)
1629                                 flags |= EmitContext.Flags.ProbingMode;
1630                         
1631                         if (ec.IsInFieldInitializer)
1632                                 flags |= EmitContext.Flags.InFieldInitializer;
1633                         
1634                         // HACK: Flag with 0 cannot be set 
1635                         if (flags != 0)
1636                                 aec_dispose = aec.Set (flags);
1637
1638                         Report.Debug (64, "RESOLVE ANONYMOUS METHOD #1", this, Location, ec, aec,
1639                                       RootScope, Parameters, Block);
1640
1641                         bool unreachable;
1642                         bool res = aec.ResolveTopBlock (ec, Block, Parameters, null, out unreachable);
1643
1644                         if (ec.InferReturnType)
1645                                 ReturnType = aec.ReturnType;
1646
1647                         if (aec_dispose != null) {
1648                                 aec_dispose.Dispose ();
1649                         }
1650
1651                         return res;
1652                 }
1653
1654                 public virtual bool Define (EmitContext ec)
1655                 {
1656                         Report.Debug (64, "DEFINE ANONYMOUS METHOD #3", this, ec, aec, Block);
1657
1658                         if (aec == null && !Compatible (ec))
1659                                 return false;
1660
1661                         // Don't define anything when we are in probing scope (nested anonymous methods)
1662                         if (ec.IsInProbingMode)
1663                                 return true;
1664
1665                         method = DoCreateMethodHost (ec);
1666
1667                         if (Scope != null)
1668                                 return true;
1669
1670                         if (!method.ResolveMembers ())
1671                                 return false;
1672                         return method.Define ();
1673                 }
1674
1675                 protected abstract Method DoCreateMethodHost (EmitContext ec);
1676
1677                 public override void Emit (EmitContext ec)
1678                 {
1679                         throw new NotSupportedException ();
1680                 }
1681
1682                 public Block Container {
1683                         get { return container; }
1684                 }
1685
1686                 public GenericMethod GenericMethod {
1687                         get { return generic; }
1688                 }
1689
1690                 public abstract bool IsIterator {
1691                         get;
1692                 }
1693
1694                 protected class AnonymousMethodMethod : Method
1695                 {
1696                         public readonly AnonymousContainer AnonymousMethod;
1697                         public readonly ScopeInfo Scope;
1698                         public readonly string RealName;
1699
1700                         public AnonymousMethodMethod (AnonymousContainer am, ScopeInfo scope,
1701                                                       GenericMethod generic, TypeExpr return_type,
1702                                                       int mod, string real_name, MemberName name,
1703                                                       Parameters parameters)
1704                                 : base (scope != null ? scope : am.Host,
1705                                         generic, return_type, mod | Modifiers.COMPILER_GENERATED, false, name, parameters, null)
1706                         {
1707                                 this.AnonymousMethod = am;
1708                                 this.Scope = scope;
1709                                 this.RealName = real_name;
1710
1711                                 if (scope != null) {
1712                                         scope.CheckMembersDefined ();
1713                                         scope.AddMethod (this);
1714                                 } else {
1715                                         ModFlags |= Modifiers.STATIC;
1716                                         am.Host.PartialContainer.AddMethod (this);
1717                                 }
1718                                 Block = am.Block;
1719                         }
1720
1721                         public override EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
1722                         {
1723                                 EmitContext aec = AnonymousMethod.aec;
1724                                 aec.ig = ig;
1725                                 aec.MethodIsStatic = Scope == null;
1726                                 return aec;
1727                         }
1728
1729                         public override void EmitExtraSymbolInfo ()
1730                         {
1731                                 SymbolWriter.SetRealMethodName (RealName);
1732                         }
1733                 }
1734         }
1735
1736         public class AnonymousMethod : AnonymousContainer
1737         {
1738                 Type DelegateType;
1739
1740                 //
1741                 // The value return by the Compatible call, this ensure that
1742                 // the code works even if invoked more than once (Resolve called
1743                 // more than once, due to the way Convert.ImplicitConversion works
1744                 //
1745                 RootScopeInfo root_scope;
1746                 ScopeInfo scope;
1747
1748                 public AnonymousMethod (RootScopeInfo root_scope,
1749                                         DeclSpace host, GenericMethod generic,
1750                                         Parameters parameters, Block container,
1751                                         ToplevelBlock block, Type return_type, Type delegate_type,
1752                                         Location loc)
1753                         : base (host, generic, parameters, container, block,
1754                                 return_type, 0, loc)
1755                 {
1756                         this.DelegateType = delegate_type;
1757                         this.root_scope = root_scope;
1758                 }
1759
1760                 public override string ContainerType {
1761                         get { return "anonymous method"; }
1762                 }
1763
1764                 public override RootScopeInfo RootScope {
1765                         get { return root_scope; }
1766                 }
1767
1768                 public override ScopeInfo Scope {
1769                         get { return scope; }
1770                 }
1771
1772                 public override bool IsIterator {
1773                         get { return false; }
1774                 }
1775
1776                 public override string GetSignatureForError ()
1777                 {
1778                         return TypeManager.CSharpName (DelegateType);
1779                 }
1780
1781                 //
1782                 // Creates the host for the anonymous method
1783                 //
1784                 protected override Method DoCreateMethodHost (EmitContext ec)
1785                 {
1786                         MemberCore mc = ec.ResolveContext as MemberCore;
1787                         string name = CompilerGeneratedClass.MakeName (mc.Name, null);
1788                         MemberName member_name;
1789
1790                         Report.Debug (128, "CREATE METHOD HOST #0", RootScope);
1791
1792                         Block b;
1793                         scope = RootScope;
1794
1795                         Report.Debug (128, "CREATE METHOD HOST #1", this, Block, Block.ScopeInfo,
1796                                       RootScope, Location);
1797
1798                         for (b = Block.Parent; b != null; b = b.Parent) {
1799                                 Report.Debug (128, "CREATE METHOD HOST #2", this, Block,
1800                                               b, b.ScopeInfo);
1801                                 if (b.ScopeInfo != null) {
1802                                         scope = b.ScopeInfo;
1803                                         break;
1804                                 }
1805                         }
1806
1807                         if (scope != null)
1808                                 scope.CheckMembersDefined ();
1809
1810                         ArrayList scopes = new ArrayList ();
1811                         if (b != null) {
1812                                 for (b = b.Parent; b != null; b = b.Parent) {
1813                                         if (b.ScopeInfo != null)
1814                                                 scopes.Add (b.ScopeInfo);
1815                                 }
1816                         }
1817
1818                         Report.Debug (128, "CREATE METHOD HOST #1", this, scope, scopes);
1819
1820                         foreach (ScopeInfo si in scopes)
1821                                 scope.CaptureScope (si);
1822
1823                         Report.Debug (128, "CREATE METHOD HOST", this, Block, container,
1824                                       RootScope, scope, scopes, Location);
1825
1826                         GenericMethod generic_method = null;
1827 #if GMCS_SOURCE
1828                         if (TypeManager.IsGenericType (DelegateType)) {
1829                                 TypeArguments args = new TypeArguments (Location);
1830
1831                                 Type dt = DelegateType.GetGenericTypeDefinition ();
1832
1833                                 Type[] tparam = TypeManager.GetTypeArguments (dt);
1834                                 for (int i = 0; i < tparam.Length; i++)
1835                                         args.Add (new SimpleName (tparam [i].Name, Location));
1836
1837                                 member_name = new MemberName (name, args, Location);
1838
1839                                 Report.Debug (128, "CREATE METHOD HOST #5", this, DelegateType,
1840                                               TypeManager.GetTypeArguments (DelegateType),
1841                                               dt, tparam, args);
1842
1843                                 generic_method = new GenericMethod (
1844                                         Host.NamespaceEntry, scope, member_name,
1845                                         new TypeExpression (ReturnType, Location), Parameters);
1846
1847                                 generic_method.SetParameterInfo (null);
1848                         } else
1849 #endif
1850                                 member_name = new MemberName (name, Location);
1851
1852                         string real_name = String.Format (
1853                                 "{0}~{1}{2}", mc.GetSignatureForError (), GetSignatureForError (),
1854                                 Parameters.GetSignatureForError ());
1855
1856                         return new AnonymousMethodMethod (
1857                                 this, scope, generic_method, new TypeExpression (ReturnType, Location),
1858                                 scope == null ? Modifiers.PRIVATE : Modifiers.INTERNAL,
1859                                 real_name, member_name, Parameters);
1860                 }
1861
1862                 public override Expression DoResolve (EmitContext ec)
1863                 {
1864                         if (!Define (ec))
1865                                 return null;
1866
1867                         return new AnonymousDelegate (this, DelegateType, Location).Resolve (ec);
1868                 }
1869
1870                 public MethodInfo GetMethodBuilder (EmitContext ec)
1871                 {
1872                         MethodInfo builder = method.MethodBuilder;
1873                         if ((Scope != null) && Scope.IsGeneric) {
1874                                 Type scope_type = Scope.GetScopeType (ec);
1875                                 if (scope_type == null)
1876                                         throw new InternalErrorException ();
1877
1878                                 MethodGroupExpr mg = (MethodGroupExpr) Expression.MemberLookup (
1879                                         ec.ContainerType, scope_type, builder.Name,
1880                                         MemberTypes.Method, Expression.AllBindingFlags | BindingFlags.NonPublic, Location);
1881                                 
1882                                 if (mg == null)
1883                                         throw new InternalErrorException ();
1884                                 builder = (MethodInfo) mg.Methods [0];
1885                         }
1886
1887 #if GMCS_SOURCE
1888                         if (!DelegateType.IsGenericType)
1889                                 return builder;
1890
1891                         Type[] targs = TypeManager.GetTypeArguments (DelegateType);
1892                         return builder.MakeGenericMethod (targs);
1893 #else
1894                         return builder;
1895 #endif
1896                 }
1897
1898                 public static void Error_AddressOfCapturedVar (string name, Location loc)
1899                 {
1900                         Report.Error (1686, loc,
1901                                       "Local variable `{0}' or its members cannot have their " +
1902                                       "address taken and be used inside an anonymous method block",
1903                                       name);
1904                 }
1905         }
1906
1907         //
1908         // This will emit the code for the delegate, as well delegate creation on the host
1909         //
1910         public class AnonymousDelegate : DelegateCreation {
1911                 readonly AnonymousMethod am;
1912
1913                 //
1914                 // if target_type is null, this means that we do not know the type
1915                 // for this delegate, and we want to infer it from the various 
1916                 // returns (implicit and explicit) from the body of this anonymous
1917                 // method.
1918                 //
1919                 // for example, the lambda: x => 1
1920                 //
1921                 public AnonymousDelegate (AnonymousMethod am, Type target_type, Location l)
1922                 {
1923                         type = target_type;
1924                         loc = l;
1925                         this.am = am;
1926                 }
1927
1928                 public override Expression DoResolve (EmitContext ec)
1929                 {
1930                         eclass = ExprClass.Value;
1931                         return this;
1932                 }
1933                 
1934                 public override void Emit (EmitContext ec)
1935                 {
1936                         //ec.ig.Emit (OpCodes.Ldstr, "EMIT ANONYMOUS DELEGATE");
1937                         //ec.ig.Emit (OpCodes.Pop);
1938
1939                         //
1940                         // Now emit the delegate creation.
1941                         //
1942                         if ((am.Method.ModFlags & Modifiers.STATIC) == 0) {
1943                                 Report.Debug (128, "EMIT ANONYMOUS DELEGATE", this, am, am.Scope, loc);
1944                                 delegate_instance_expression = am.Scope.GetScopeInitializer (ec);
1945
1946                                 if (delegate_instance_expression == null)
1947                                         throw new InternalErrorException ();
1948                         }
1949
1950                         constructor_method = Delegate.GetConstructor (ec.ContainerType, type);
1951 #if MS_COMPATIBLE
1952                         if (type.IsGenericType && type is TypeBuilder)
1953                                 constructor_method = TypeBuilder.GetConstructor (type, (ConstructorInfo)constructor_method);
1954 #endif
1955                         
1956                         delegate_method = am.GetMethodBuilder (ec);
1957                         base.Emit (ec);
1958
1959                         //ec.ig.Emit (OpCodes.Ldstr, "EMIT ANONYMOUS DELEGATE DONE");
1960                         //ec.ig.Emit (OpCodes.Pop);
1961
1962                         Report.Debug (128, "EMIT ANONYMOUS DELEGATE DONE", this, am, am.Scope, loc);
1963                 }
1964         }
1965
1966         //
1967         // Anonymous type container
1968         //
1969         public class AnonymousTypeClass : CompilerGeneratedClass
1970         {
1971                 static int types_counter;
1972                 public const string ClassNamePrefix = "<>__AnonType";
1973                 public const string SignatureForError = "anonymous type";
1974                 
1975                 static readonly IntConstant FNV_prime = new IntConstant (16777619, Location.Null);
1976
1977                 readonly ArrayList parameters;
1978
1979                 private AnonymousTypeClass (DeclSpace parent, MemberName name, ArrayList parameters, Location loc)
1980                         : base (parent, name, Modifiers.SEALED, loc)
1981                 {
1982                         this.parameters = parameters;
1983                 }
1984
1985                 public static AnonymousTypeClass Create (TypeContainer parent, ArrayList parameters, Location loc)
1986                 {
1987                         if (RootContext.Version <= LanguageVersion.ISO_2)
1988                                 Report.FeatureIsNotAvailable (loc, "anonymous types");
1989                         
1990                         string name = ClassNamePrefix + types_counter++;
1991
1992                         SimpleName [] t_args = new SimpleName [parameters.Count];
1993                         Parameter [] ctor_params = new Parameter [parameters.Count];
1994                         for (int i = 0; i < parameters.Count; ++i) {
1995                                 AnonymousTypeParameter p = (AnonymousTypeParameter) parameters [i];
1996
1997                                 t_args [i] = new SimpleName ("<" + p.Name + ">__T", p.Location);
1998                                 ctor_params [i] = new Parameter (t_args [i], p.Name, 0, null, p.Location);
1999                         }
2000
2001                         //
2002                         // Create generic anonymous type host with generic arguments
2003                         // named upon properties names
2004                         //
2005                         AnonymousTypeClass a_type = new AnonymousTypeClass (parent.NamespaceEntry.SlaveDeclSpace,
2006                                 new MemberName (name, new TypeArguments (loc, t_args), loc), parameters, loc);
2007
2008                         if (parameters.Count > 0)
2009                                 a_type.SetParameterInfo (null);
2010
2011                         Constructor c = new Constructor (a_type, name, Modifiers.PUBLIC,
2012                                 new Parameters (ctor_params), null, loc);
2013                         c.OptAttributes = a_type.GetDebuggerHiddenAttribute ();
2014                         c.Block = new ToplevelBlock (c.Parameters, loc);
2015
2016                         // 
2017                         // Create fields and contructor body with field initialization
2018                         //
2019                         bool error = false;
2020                         for (int i = 0; i < parameters.Count; ++i) {
2021                                 AnonymousTypeParameter p = (AnonymousTypeParameter) parameters [i];
2022
2023                                 Field f = new Field (a_type, t_args [i], Modifiers.PRIVATE | Modifiers.READONLY,
2024                                         "<" + p.Name + ">", null, p.Location);
2025
2026                                 if (!a_type.AddField (f)) {
2027                                         error = true;
2028                                         Report.Error (833, p.Location, "`{0}': An anonymous type cannot have multiple properties with the same name",
2029                                                 p.Name);
2030                                         continue;
2031                                 }
2032
2033                                 c.Block.AddStatement (new StatementExpression (
2034                                         new Assign (new MemberAccess (new This (p.Location), f.Name),
2035                                                 c.Block.GetParameterReference (p.Name, p.Location))));
2036
2037                                 ToplevelBlock get_block = new ToplevelBlock (p.Location);
2038                                 get_block.AddStatement (new Return (
2039                                         new MemberAccess (new This (p.Location), f.Name), p.Location));
2040                                 Accessor get_accessor = new Accessor (get_block, 0, null, p.Location);
2041                                 Property prop = new Property (a_type, t_args [i], Modifiers.PUBLIC, false,
2042                                         new MemberName (p.Name, p.Location), null, get_accessor, null, false);
2043                                 a_type.AddProperty (prop);
2044                         }
2045
2046                         if (error)
2047                                 return null;
2048
2049                         a_type.AddConstructor (c);
2050                         return a_type;
2051                 }
2052
2053                 protected override bool AddToContainer (MemberCore symbol, string name)
2054                 {
2055                         MemberCore mc = (MemberCore) defined_names [name];
2056
2057                         if (mc == null) {
2058                                 defined_names.Add (name, symbol);
2059                                 return true;
2060                         }
2061
2062                         Report.SymbolRelatedToPreviousError (mc);
2063                         return false;
2064                 }
2065
2066                 void DefineOverrides ()
2067                 {
2068                         Location loc = Location;
2069
2070                         Method equals = new Method (this, null, TypeManager.system_boolean_expr,
2071                                 Modifiers.PUBLIC | Modifiers.OVERRIDE, false, new MemberName ("Equals", loc),
2072                                 new Parameters (new Parameter (TypeManager.system_object_expr, "obj", 0, null, loc)),
2073                                 GetDebuggerHiddenAttribute ());
2074
2075                         Method tostring = new Method (this, null, TypeManager.system_string_expr,
2076                                 Modifiers.PUBLIC | Modifiers.OVERRIDE, false, new MemberName ("ToString", loc),
2077                                 Mono.CSharp.Parameters.EmptyReadOnlyParameters, GetDebuggerHiddenAttribute ());
2078
2079                         ToplevelBlock equals_block = new ToplevelBlock (equals.Parameters, loc);
2080                         TypeExpr current_type;
2081                         if (IsGeneric)
2082                                 current_type = new ConstructedType (TypeBuilder, TypeParameters, loc);
2083                         else
2084                                 current_type = new TypeExpression (TypeBuilder, loc);
2085
2086                         equals_block.AddVariable (current_type, "other", loc);
2087                         LocalVariableReference other_variable = new LocalVariableReference (equals_block, "other", loc);
2088
2089                         MemberAccess system_collections_generic = new MemberAccess (new MemberAccess (
2090                                 new SimpleName ("System", loc), "Collections", loc), "Generic", loc);
2091
2092                         Expression rs_equals = null;
2093                         Expression string_concat = new StringConstant ("<empty type>", loc);
2094                         Expression rs_hashcode = new IntConstant (-2128831035, loc);
2095                         for (int i = 0; i < parameters.Count; ++i) {
2096                                 AnonymousTypeParameter p = (AnonymousTypeParameter) parameters [i];
2097                                 Field f = (Field) Fields [i];
2098
2099                                 MemberAccess equality_comparer = new MemberAccess (new MemberAccess (
2100                                         system_collections_generic, "EqualityComparer",
2101                                                 new TypeArguments (loc, new SimpleName (TypeParameters [i].Name, loc)), loc),
2102                                                 "Default", loc);
2103
2104                                 ArrayList arguments_equal = new ArrayList (2);
2105                                 arguments_equal.Add (new Argument (new MemberAccess (new This (f.Location), f.Name)));
2106                                 arguments_equal.Add (new Argument (new MemberAccess (other_variable, f.Name)));
2107
2108                                 Expression field_equal = new Invocation (new MemberAccess (equality_comparer,
2109                                         "Equals", loc), arguments_equal);
2110
2111                                 ArrayList arguments_hashcode = new ArrayList (1);
2112                                 arguments_hashcode.Add (new Argument (new MemberAccess (new This (f.Location), f.Name)));
2113                                 Expression field_hashcode = new Invocation (new MemberAccess (equality_comparer,
2114                                         "GetHashCode", loc), arguments_hashcode);
2115
2116                                 rs_hashcode = new Binary (Binary.Operator.Multiply,
2117                                         new Binary (Binary.Operator.ExclusiveOr, rs_hashcode, field_hashcode),
2118                                         FNV_prime);
2119
2120                                 Expression field_to_string = new Conditional (new Binary (Binary.Operator.Inequality,
2121                                         new MemberAccess (new This (f.Location), f.Name), new NullLiteral (loc)),
2122                                         new Invocation (new MemberAccess (
2123                                                 new MemberAccess (new This (f.Location), f.Name), "ToString"), null),
2124                                         new StringConstant ("<null>", loc));
2125
2126                                 if (rs_equals == null) {
2127                                         rs_equals = field_equal;
2128                                         string_concat = new Binary (Binary.Operator.Addition,
2129                                                 new StringConstant (p.Name + " = ", loc),
2130                                                 field_to_string);
2131                                         continue;
2132                                 }
2133
2134                                 //
2135                                 // Implementation of ToString () body using string concatenation
2136                                 //                              
2137                                 string_concat = new Binary (Binary.Operator.Addition,
2138                                         new Binary (Binary.Operator.Addition,
2139                                                 string_concat,
2140                                                 new StringConstant (", " + p.Name + " = ", loc)),
2141                                         field_to_string);
2142
2143                                 rs_equals = new Binary (Binary.Operator.LogicalAnd, rs_equals, field_equal);
2144                         }
2145
2146                         //
2147                         // Equals (object obj) override
2148                         //
2149                         equals_block.AddStatement (new StatementExpression (
2150                                 new Assign (other_variable,
2151                                         new As (equals_block.GetParameterReference ("obj", loc),
2152                                                 current_type, loc), loc)));
2153
2154                         Expression equals_test = new Binary (Binary.Operator.Inequality, other_variable, new NullLiteral (loc));
2155                         if (rs_equals != null)
2156                                 equals_test = new Binary (Binary.Operator.LogicalAnd, equals_test, rs_equals);
2157                         equals_block.AddStatement (new Return (equals_test, loc));
2158
2159                         equals.Block = equals_block;
2160                         equals.ResolveMembers ();
2161                         AddMethod (equals);
2162
2163                         //
2164                         // GetHashCode () override
2165                         //
2166                         Method hashcode = new Method (this, null, TypeManager.system_int32_expr,
2167                                 Modifiers.PUBLIC | Modifiers.OVERRIDE, false, new MemberName ("GetHashCode", loc),
2168                                 Mono.CSharp.Parameters.EmptyReadOnlyParameters, GetDebuggerHiddenAttribute ());
2169
2170                         //
2171                         // Modified FNV with good avalanche behavior and uniform
2172                         // distribution with larger hash sizes.
2173                         //
2174                         // const int FNV_prime = 16777619;
2175                         // int hash = (int) 2166136261;
2176                         // foreach (int d in data)
2177                         //     hash = (hash ^ d) * FNV_prime;
2178                         // hash += hash << 13;
2179                         // hash ^= hash >> 7;
2180                         // hash += hash << 3;
2181                         // hash ^= hash >> 17;
2182                         // hash += hash << 5;
2183
2184                         ToplevelBlock hashcode_block = new ToplevelBlock (loc);
2185                         hashcode_block.AddVariable (TypeManager.system_int32_expr, "hash", loc);
2186                         LocalVariableReference hash_variable = new LocalVariableReference (hashcode_block, "hash", loc);
2187                         hashcode_block.AddStatement (new StatementExpression (
2188                                 new Assign (hash_variable, rs_hashcode)));
2189
2190                         hashcode_block.AddStatement (new StatementExpression (
2191                                 new CompoundAssign (Binary.Operator.Addition, hash_variable,
2192                                         new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (13, loc)))));
2193                         hashcode_block.AddStatement (new StatementExpression (
2194                                 new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable,
2195                                         new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (7, loc)))));
2196                         hashcode_block.AddStatement (new StatementExpression (
2197                                 new CompoundAssign (Binary.Operator.Addition, hash_variable,
2198                                         new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (3, loc)))));
2199                         hashcode_block.AddStatement (new StatementExpression (
2200                                 new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable,
2201                                         new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (17, loc)))));
2202                         hashcode_block.AddStatement (new StatementExpression (
2203                                 new CompoundAssign (Binary.Operator.Addition, hash_variable,
2204                                         new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (5, loc)))));
2205
2206                         hashcode_block.AddStatement (new Return (hash_variable, loc));
2207                         hashcode.Block = hashcode_block;
2208                         hashcode.ResolveMembers ();
2209                         AddMethod (hashcode);
2210
2211                         //
2212                         // ToString () override
2213                         //
2214
2215                         ToplevelBlock tostring_block = new ToplevelBlock (loc);
2216                         tostring_block.AddStatement (new Return (string_concat, loc));
2217                         tostring.Block = tostring_block;
2218                         tostring.ResolveMembers ();
2219                         AddMethod (tostring);
2220                 }
2221
2222                 public override bool DefineMembers ()
2223                 {
2224                         DefineOverrides ();
2225
2226                         return base.DefineMembers ();
2227                 }
2228
2229                 Attributes GetDebuggerHiddenAttribute ()
2230                 {
2231                         return new Attributes (new Attribute (null, null,
2232                                 "System.Diagnostics.DebuggerHiddenAttribute", null, Location, false));
2233                 }
2234
2235                 public override string GetSignatureForError ()
2236                 {
2237                         return SignatureForError;
2238                 }
2239
2240                 public ArrayList Parameters {
2241                         get {
2242                                 return parameters;
2243                         }
2244                 }
2245         }
2246 }