2007-10-12 Marek Safar <marek.safar@gmail.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                 protected string MakeFieldName (string local_name)
414                 {
415                         return "<" + ID + ":" + local_name + ">";
416                 }
417
418                 protected virtual ScopeInitializer CreateScopeInitializer ()
419                 {
420                         return new ScopeInitializer (this);
421                 }
422
423                 protected abstract class CapturedVariable : Variable
424                 {
425                         public readonly ScopeInfo Scope;
426                         public readonly string Name;
427
428                         public FieldExpr FieldInstance;
429                         protected Field field;
430
431                         protected CapturedVariable (ScopeInfo scope, string name)
432                         {
433                                 this.Scope = scope;
434                                 this.Name = name;
435                         }
436
437                         protected CapturedVariable (ScopeInfo scope, string name, Type type)
438                                 : this (scope, name)
439                         {
440                                 this.field = scope.CaptureVariable (
441                                         scope.MakeFieldName (name), scope.RootScope.InflateType (type));
442                         }
443
444                         public Field Field {
445                                 get { return field; }
446                         }
447
448                         public override Type Type {
449                                 get { return Field.MemberType; }
450                         }
451
452                         public override bool HasInstance {
453                                 get { return true; }
454                         }
455
456                         public override bool NeedsTemporary {
457                                 get { return true; }
458                         }
459
460                         protected FieldInfo GetField (EmitContext ec)
461                         {
462                                 if ((ec.CurrentBlock != null) &&
463                                     (ec.CurrentBlock.Toplevel != Scope.ScopeBlock.Toplevel))
464                                         return Field.FieldBuilder;
465                                 else
466                                         return FieldInstance.FieldInfo;
467                         }
468
469                         public override void EmitInstance (EmitContext ec)
470                         {
471                                 if ((ec.CurrentAnonymousMethod != null) &&
472                                     (ec.CurrentAnonymousMethod.Scope == Scope)) {
473                                         ec.ig.Emit (OpCodes.Ldarg_0);
474                                         return;
475                                 }
476
477                                 Scope.EmitScopeInstance (ec);
478                         }
479
480                         public override void Emit (EmitContext ec)
481                         {
482                                 ec.ig.Emit (OpCodes.Ldfld, GetField (ec));
483                         }
484
485                         public override void EmitAssign (EmitContext ec)
486                         {
487                                 ec.ig.Emit (OpCodes.Stfld, GetField (ec));
488                         }
489
490                         public override void EmitAddressOf (EmitContext ec)
491                         {
492                                 ec.ig.Emit (OpCodes.Ldflda, GetField (ec));
493                         }
494                 }
495
496                 protected class CapturedParameter : CapturedVariable {
497                         public readonly Parameter Parameter;
498                         public readonly int Idx;
499
500                         public CapturedParameter (ScopeInfo scope, Parameter par, int idx)
501                                 : base (scope, par.Name, par.ParameterType)
502                         {
503                                 this.Parameter = par;
504                                 this.Idx = idx;
505                         }
506
507                         public override string ToString ()
508                         {
509                                 return String.Format ("{0} ({1}:{2}:{3})", GetType (), Field,
510                                                       Parameter.Name, Idx);
511                         }
512                 }
513
514                 protected class CapturedLocal : CapturedVariable {
515                         public readonly LocalInfo Local;
516
517                         public CapturedLocal (ScopeInfo scope, LocalInfo local)
518                                 : base (scope, local.Name, local.VariableType)
519                         {
520                                 this.Local = local;
521                         }
522
523                         public override string ToString ()
524                         {
525                                 return String.Format ("{0} ({1}:{2})", GetType (), Field,
526                                                       Local.Name);
527                         }
528                 }
529
530                 protected class CapturedThis : CapturedVariable {
531                         public CapturedThis (RootScopeInfo host)
532                                 : base (host, "<>THIS", host.ParentType)
533                         { }
534                 }
535
536                 protected class CapturedScope : CapturedVariable {
537                         public readonly ScopeInfo ChildScope;
538
539                         public CapturedScope (ScopeInfo root, ScopeInfo child)
540                                 : base (root, "scope" + child.ID)
541                         {
542                                 this.ChildScope = child;
543                         }
544
545                         public bool DefineMembers ()
546                         {
547                                 Type type = ChildScope.IsGeneric ?
548                                         ChildScope.CurrentType : ChildScope.TypeBuilder;
549                                 Report.Debug (128, "CAPTURED SCOPE DEFINE MEMBERS", this, Scope,
550                                               ChildScope, Name, type);
551                                 if (type == null)
552                                         throw new InternalErrorException ();
553                                 field = Scope.CaptureVariable (
554                                         Scope.MakeFieldName (Name), Scope.InflateType (type));
555                                 return true;
556                         }
557
558                         public override string ToString ()
559                         {
560                                 return String.Format ("CapturedScope ({1} captured in {0})",
561                                                       Scope, ChildScope);
562                         }
563                 }
564
565                 static void DoPath (StringBuilder sb, ScopeInfo start)
566                 {
567                         sb.Append ((start.ID).ToString ());
568                 }
569                 
570                 public override string ToString ()
571                 {
572                         StringBuilder sb = new StringBuilder ();
573                         
574                         sb.Append ("{");
575                         DoPath (sb, this);
576                         sb.Append ("}");
577
578                         return sb.ToString ();
579                 }
580
581                 protected class ScopeInitializer : ExpressionStatement
582                 {
583                         ScopeInfo scope;
584                         CapturedVariable captured_scope;
585                         LocalBuilder scope_instance;
586                         ConstructorInfo scope_ctor;
587
588                         bool initialized;
589
590                         public ScopeInitializer (ScopeInfo scope)
591                         {
592                                 this.scope = scope;
593                                 this.loc = scope.Location;
594                                 eclass = ExprClass.Value;
595                         }
596
597                         public ScopeInfo Scope {
598                                 get { return scope; }
599                         }
600
601                         public override Expression DoResolve (EmitContext ec)
602                         {
603                                 if (scope_ctor != null)
604                                         return this;
605
606                                 Report.Debug (64, "RESOLVE SCOPE INITIALIZER BASE", this, Scope,
607                                               ec, ec.CurrentBlock);
608
609                                 type = Scope.GetScopeType (ec);
610                                 if (type == null)
611                                         throw new InternalErrorException ();
612
613                                 if (!DoResolveInternal (ec))
614                                         throw new InternalErrorException ();
615
616                                 return this;
617                         }
618
619                         protected virtual bool DoResolveInternal (EmitContext ec)
620                         {
621                                 MethodGroupExpr mg = (MethodGroupExpr) MemberLookupFinal (
622                                         ec, ec.ContainerType, type, ".ctor", MemberTypes.Constructor,
623                                         AllBindingFlags | BindingFlags.DeclaredOnly, loc);
624                                 if (mg == null)
625                                         throw new InternalErrorException ();
626
627                                 scope_ctor = (ConstructorInfo) mg.Methods [0];
628
629                                 Report.Debug (128, "RESOLVE THE INIT", this, Scope, Scope.RootScope,
630                                               Scope.RootScope.GetType ());
631
632                                 ScopeInfo host = Scope.RootScope;
633                                 if ((Scope != host) && (Scope.RootScope is IteratorHost)) {
634                                         captured_scope = host.GetCapturedScope (Scope);
635                                         Type root = host.GetScopeType (ec);
636                                         FieldExpr fe = (FieldExpr) Expression.MemberLookup (
637                                                 type, root, captured_scope.Field.Name, loc);
638                                         if (fe == null)
639                                                 throw new InternalErrorException ();
640
641                                         fe.InstanceExpression = this;
642                                         captured_scope.FieldInstance = fe;
643
644                                         Report.Debug (128, "RESOLVE THE INIT #1", this,
645                                                       captured_scope, fe);
646                                 } else
647                                         scope_instance = ec.ig.DeclareLocal (type);
648
649                                 foreach (CapturedLocal local in Scope.locals.Values) {
650                                         FieldExpr fe = (FieldExpr) Expression.MemberLookup (
651                                                 ec.ContainerType, type, local.Field.Name, loc);
652                                         Report.Debug (64, "RESOLVE SCOPE INITIALIZER #2", this, Scope,
653                                                       Scope, ec, ec.ContainerType, type,
654                                                       local.Field, local.Field.Name, loc, fe);
655                                         if (fe == null)
656                                                 throw new InternalErrorException ();
657
658                                         fe.InstanceExpression = this;
659                                         local.FieldInstance = fe;
660                                 }
661
662                                 if (Scope.HostsParameters) {
663                                         foreach (CapturedParameter cp in Scope.captured_params.Values) {
664                                                 FieldExpr fe = (FieldExpr) Expression.MemberLookup (
665                                                         ec.ContainerType, type, cp.Field.Name, loc);
666                                                 if (fe == null)
667                                                         throw new InternalErrorException ();
668
669                                                 fe.InstanceExpression = this;
670                                                 cp.FieldInstance = fe;
671                                         }
672                                 }
673
674                                 foreach (CapturedScope scope in Scope.CapturedScopes) {
675                                         FieldExpr fe = (FieldExpr) Expression.MemberLookup (
676                                                 ec.ContainerType, type, scope.Field.Name, loc);
677                                         Report.Debug (64, "RESOLVE SCOPE INITIALIZER #3", this, Scope,
678                                                       scope, ec, ec.ContainerType, type,
679                                                       scope.Field, scope.Field.Name, loc, fe);
680                                         if (fe == null)
681                                                 throw new InternalErrorException ();
682
683                                         fe.InstanceExpression = this;
684                                         scope.FieldInstance = fe;
685                                 }
686
687                                 return true;
688                         }
689
690                         protected virtual void EmitParameterReference (EmitContext ec,
691                                                                        CapturedParameter cp)
692                         {
693                                 int extra = ec.MethodIsStatic ? 0 : 1;
694                                 ParameterReference.EmitLdArg (ec.ig, cp.Idx + extra);
695                         }
696
697                         static int next_id;
698                         int id = ++next_id;
699
700                         protected virtual void DoEmit (EmitContext ec)
701                         {
702                                 if ((ec.CurrentBlock != null) &&
703                                     (ec.CurrentBlock.Toplevel != Scope.ScopeBlock.Toplevel)) {
704                                         ec.ig.Emit (OpCodes.Ldarg_0);
705
706                                         if (ec.CurrentAnonymousMethod != null) {
707                                                 ScopeInfo host = ec.CurrentAnonymousMethod.Scope;
708                                                 Variable captured = host.GetCapturedScope (scope);
709                                                 Report.Debug (128, "EMIT SCOPE INSTANCE #2",
710                                                               ec.CurrentAnonymousMethod, host,
711                                                               scope, captured);
712                                                 if (captured != null)
713                                                         captured.Emit (ec);
714                                         }
715                                 } else if (scope_instance != null)
716                                         ec.ig.Emit (OpCodes.Ldloc, scope_instance);
717                                 else {
718                                         Report.Debug (128, "DO EMIT", this, Scope, ec,
719                                                       scope_instance, captured_scope);
720                                         captured_scope.EmitInstance (ec);
721                                         captured_scope.Emit (ec);
722                                 }
723                         }
724
725                         protected void DoEmitInstance (EmitContext ec)
726                         {
727                                 Report.Debug (128, "DO EMIT INSTANCE", this, Scope, ec,
728                                               scope_instance, captured_scope);
729
730                                 if (scope_instance != null)
731                                         ec.ig.Emit (OpCodes.Ldloc, scope_instance);
732                                 else
733                                         captured_scope.EmitInstance (ec);
734                         }
735
736                         protected virtual void EmitScopeConstructor (EmitContext ec)
737                         {
738                                 ec.ig.Emit (OpCodes.Newobj, scope_ctor);
739                         }
740
741                         public override void Emit (EmitContext ec)
742                         {
743                                 if (!initialized)
744                                         throw new InternalErrorException (
745                                                 "Scope {0} not initialized yet", scope);
746
747                                 DoEmit (ec);
748                         }
749
750                         public override void EmitStatement (EmitContext ec)
751                         {
752                                 if (initialized)
753                                         return;
754
755                                 DoEmitStatement (ec);
756                                 initialized = true;
757                         }
758
759                         protected virtual void DoEmitStatement (EmitContext ec)
760                         {
761                                 Report.Debug (128, "EMIT SCOPE INITIALIZER STATEMENT", this, id,
762                                               Scope, scope_instance, ec);
763
764                                 ec.ig.Emit (OpCodes.Nop);
765                                 ec.ig.Emit (OpCodes.Ldc_I4, id);
766                                 ec.ig.Emit (OpCodes.Pop);
767                                 ec.ig.Emit (OpCodes.Nop);
768
769                                 if (scope_instance == null)
770                                         ec.ig.Emit (OpCodes.Ldarg_0);
771                                 EmitScopeConstructor (ec);
772                                 if (scope_instance != null)
773                                         ec.ig.Emit (OpCodes.Stloc, scope_instance);
774                                 else
775                                         captured_scope.EmitAssign (ec);
776
777                                 if (Scope.HostsParameters) {
778                                         foreach (CapturedParameter cp in Scope.captured_params.Values) {
779                                                 Report.Debug (128, "EMIT SCOPE INIT #6", this,
780                                                               ec, ec.IsStatic, Scope, cp, cp.Field.Name);
781                                                 DoEmitInstance (ec);
782                                                 EmitParameterReference (ec, cp);
783                                                 ec.ig.Emit (OpCodes.Stfld, cp.FieldInstance.FieldInfo);
784                                         }
785                                 }
786
787                                 if (Scope is IteratorHost)
788                                         return;
789
790                                 foreach (CapturedScope scope in Scope.CapturedScopes) {
791                                         ScopeInfo child = scope.ChildScope;
792
793                                         Report.Debug (128, "EMIT SCOPE INIT #5", this, Scope,
794                                                       scope.Scope, scope.ChildScope);
795
796                                         ExpressionStatement init = child.GetScopeInitializer (ec);
797                                         init.EmitStatement (ec);
798
799                                         DoEmit (ec);
800                                         scope.ChildScope.EmitScopeInstance (ec);
801                                         scope.EmitAssign (ec);
802                                 }
803                         }
804                 }
805         }
806
807         public class RootScopeInfo : ScopeInfo
808         {
809                 public RootScopeInfo (ToplevelBlock toplevel, DeclSpace parent,
810                                       GenericMethod generic, Location loc)
811                         : base (toplevel, parent, generic, loc)
812                 {
813                         scopes = new ArrayList ();
814                 }
815
816                 TypeExpr parent_type;
817                 CapturedVariableField parent_link;
818                 CapturedThis this_variable;
819                 protected ArrayList scopes;
820
821                 public virtual bool IsIterator {
822                         get { return false; }
823                 }
824
825                 public RootScopeInfo ParentHost {
826                         get { return Parent.PartialContainer as RootScopeInfo; }
827                 }
828
829                 public Type ParentType {
830                         get { return parent_type.Type; }
831                 }
832
833                 public Field ParentLink {
834                         get { return parent_link; }
835                 }
836
837                 protected CapturedThis THIS {
838                         get { return this_variable; }
839                 }
840
841                 public Variable CaptureThis ()
842                 {
843                         if (ParentHost != null)
844                                 return ParentHost.CaptureThis ();
845
846                         CheckMembersDefined ();
847                         if (this_variable == null)
848                                 this_variable = new CapturedThis (this);
849                         return this_variable;
850                 }
851
852                 public void AddScope (ScopeInfo scope)
853                 {
854                         scopes.Add (scope);
855                 }
856
857                 bool linked;
858                 public void LinkScopes ()
859                 {
860                         Report.Debug (128, "LINK SCOPES", this, linked, scopes);
861
862                         if (linked)
863                                 return;
864
865                         linked = true;
866                         if (ParentHost != null)
867                                 ParentHost.LinkScopes ();
868
869                         foreach (ScopeInfo si in scopes) {
870                                 if (!si.Define ())
871                                         throw new InternalErrorException ();
872                                 if (si.DefineType () == null)
873                                         throw new InternalErrorException ();
874                                 if (!si.ResolveType ())
875                                         throw new InternalErrorException ();
876                         }
877
878                         foreach (ScopeInfo si in scopes) {
879                                 if (!si.ResolveMembers ())
880                                         throw new InternalErrorException ();
881                                 if (!si.DefineMembers ())
882                                         throw new InternalErrorException ();
883                         }
884                 }
885
886                 protected override ScopeInitializer CreateScopeInitializer ()
887                 {
888                         return new RootScopeInitializer (this);
889                 }
890
891                 protected override bool DefineNestedTypes ()
892                 {
893                         if (Parent.IsGeneric) {
894                                 parent_type = new ConstructedType (
895                                         Parent.TypeBuilder, Parent.TypeParameters, Location);
896                                 parent_type = parent_type.ResolveAsTypeTerminal (this, false);
897                                 if ((parent_type == null) || (parent_type.Type == null))
898                                         return false;
899                         } else {
900                                 parent_type = new TypeExpression (Parent.TypeBuilder, Location);
901                         }
902
903                         CompilerGeneratedClass parent = Parent.PartialContainer as CompilerGeneratedClass;
904                         if (parent != null)
905                                 parent_link = new CapturedVariableField (this, "<>parent", parent_type);
906
907                         return base.DefineNestedTypes ();
908                 }
909
910                 protected override bool DoDefineMembers ()
911                 {
912                         ArrayList args = new ArrayList ();
913                         if (this is IteratorHost)
914                                 args.Add (new Parameter (
915                                         TypeManager.int32_type, "$PC", Parameter.Modifier.NONE,
916                                         null, Location));
917
918                         Field pfield;
919                         if (Parent is CompilerGeneratedClass)
920                                 pfield = parent_link;
921                         else
922                                 pfield = this_variable !=  null ? this_variable.Field : null;
923                         if (pfield != null)
924                                 args.Add (new Parameter (
925                                         pfield.MemberType, "parent", Parameter.Modifier.NONE,
926                                         null, Location));
927
928                         Parameter[] ctor_params = new Parameter [args.Count];
929                         args.CopyTo (ctor_params, 0);
930                         Constructor ctor = new Constructor (
931                                 this, MemberName.Name, Modifiers.PUBLIC,
932                                 new Parameters (ctor_params),
933                                 new GeneratedBaseInitializer (Location),
934                                 Location);
935                         AddConstructor (ctor);
936
937                         ctor.Block = new ToplevelBlock (null, Location);
938                         ctor.Block.AddStatement (new TheCtor (this));
939
940                         return base.DoDefineMembers ();
941                 }
942
943                 protected virtual void EmitScopeConstructor (EmitContext ec)
944                 {
945                         int pos = (this is IteratorHost) ? 2 : 1;
946
947                         Field pfield;
948                         if (Parent is CompilerGeneratedClass)
949                                 pfield = parent_link;
950                         else
951                                 pfield = this_variable !=  null ? this_variable.Field : null;
952
953                         if (pfield != null) {
954                                 ec.ig.Emit (OpCodes.Ldarg_0);
955                                 ec.ig.Emit (OpCodes.Ldarg, pos);
956                                 ec.ig.Emit (OpCodes.Stfld, pfield.FieldBuilder);
957                                 pos++;
958                         }
959                 }
960
961                 protected class TheCtor : Statement
962                 {
963                         RootScopeInfo host;
964
965                         public TheCtor (RootScopeInfo host)
966                         {
967                                 this.host = host;
968                         }
969
970                         public override bool Resolve (EmitContext ec)
971                         {
972                                 return true;
973                         }
974
975                         protected override void DoEmit (EmitContext ec)
976                         {
977                                 host.EmitScopeConstructor (ec);
978                         }
979                 }
980
981                 protected class RootScopeInitializer : ScopeInitializer
982                 {
983                         RootScopeInfo host;
984
985                         public RootScopeInitializer (RootScopeInfo host)
986                                 : base (host)
987                         {
988                                 this.host = host;
989                         }
990
991                         public RootScopeInfo Host {
992                                 get { return host; }
993                         }
994
995                         protected override bool DoResolveInternal (EmitContext ec)
996                         {
997                                 Report.Debug (64, "RESOLVE ANONYMOUS METHOD HOST INITIALIZER",
998                                               this, Host, Host.ParentType, loc);
999
1000                                 if (Host.THIS != null) {
1001                                         FieldExpr fe = (FieldExpr) Expression.MemberLookup (
1002                                                 ec.ContainerType, type, Host.THIS.Field.Name, loc);
1003                                         if (fe == null)
1004                                                 throw new InternalErrorException ();
1005
1006                                         fe.InstanceExpression = this;
1007                                         Host.THIS.FieldInstance = fe;
1008                                 }
1009
1010                                 return base.DoResolveInternal (ec);
1011                         }
1012
1013                         protected virtual bool IsGetEnumerator {
1014                                 get { return false; }
1015                         }
1016
1017                         protected override void EmitScopeConstructor (EmitContext ec)
1018                         {
1019                                 if (host.THIS != null) {
1020                                         ec.ig.Emit (OpCodes.Ldarg_0);
1021                                         if (IsGetEnumerator)
1022                                                 ec.ig.Emit (OpCodes.Ldfld, host.THIS.Field.FieldBuilder);
1023                                         else if (host.THIS.Type.IsValueType)
1024                                                 Expression.LoadFromPtr (ec.ig, host.THIS.Type);
1025                                 } else if (host.ParentLink != null)
1026                                         ec.ig.Emit (OpCodes.Ldarg_0);
1027
1028                                 base.EmitScopeConstructor (ec);
1029                         }
1030                 }
1031
1032         }
1033
1034         public interface IAnonymousContainer
1035         {
1036                 Block Container {
1037                         get;
1038                 }
1039
1040                 GenericMethod GenericMethod {
1041                         get;
1042                 }
1043
1044                 RootScopeInfo RootScope {
1045                         get;
1046                 }
1047
1048                 bool IsIterator {
1049                         get;
1050                 }
1051         }
1052
1053         public interface IAnonymousHost
1054         {
1055                 //
1056                 // Invoked if a yield statement is found in the body
1057                 //
1058                 void SetYields ();
1059
1060                 //
1061                 // Invoked if an anonymous method is found in the body
1062                 //
1063                 void AddAnonymousMethod (AnonymousMethodExpression anonymous);
1064         }
1065
1066         public class AnonymousMethodExpression : Expression, IAnonymousContainer, IAnonymousHost
1067         {
1068                 public readonly AnonymousMethodExpression Parent;
1069                 public readonly TypeContainer Host;
1070                 public readonly Parameters Parameters;
1071
1072                 public ToplevelBlock Block;
1073
1074                 protected Block container;
1075                 protected readonly GenericMethod generic;
1076
1077                 public Block Container {
1078                         get { return container; }
1079                 }
1080
1081                 public GenericMethod GenericMethod {
1082                         get { return generic; }
1083                 }
1084
1085                 public RootScopeInfo RootScope {
1086                         get { return root_scope; }
1087                 }
1088
1089                 public AnonymousMethodExpression (AnonymousMethodExpression parent,
1090                                                   GenericMethod generic, TypeContainer host,
1091                                                   Parameters parameters, Block container,
1092                                                   Location loc)
1093                 {
1094                         this.Parent = parent;
1095                         this.generic = parent != null ? null : generic;
1096                         this.Host = host;
1097                         this.Parameters = parameters;
1098                         this.container = container;
1099                         this.loc = loc;
1100
1101                         Report.Debug (64, "NEW ANONYMOUS METHOD EXPRESSION", this, parent, host,
1102                                       container, loc);
1103
1104                         if (parent != null)
1105                                 parent.AddAnonymousMethod (this);
1106                 }
1107
1108                 ArrayList children;
1109                 RootScopeInfo root_scope;
1110
1111                 static int next_index;
1112
1113                 void IAnonymousHost.SetYields ()
1114                 {
1115                         throw new InvalidOperationException ();
1116                 }
1117
1118                 public void AddAnonymousMethod (AnonymousMethodExpression anonymous)
1119                 {
1120                         if (children == null)
1121                                 children = new ArrayList ();
1122                         children.Add (anonymous);
1123                 }
1124
1125                 public bool CreateAnonymousHelpers ()
1126                 {
1127                         Report.Debug (64, "ANONYMOUS METHOD EXPRESSION CREATE ROOT SCOPE",
1128                                       this, Host, container, loc);
1129
1130                         if (container != null)
1131                                 root_scope = container.Toplevel.CreateRootScope (Host);
1132
1133                         if (children != null) {
1134                                 foreach (AnonymousMethodExpression child in children) {
1135                                         if (!child.CreateAnonymousHelpers ())
1136                                                 return false;
1137                                 }
1138                         }
1139
1140                         return true;
1141                 }
1142
1143                 public override string ExprClassName {
1144                         get {
1145                                 return "anonymous method";
1146                         }
1147                 }
1148
1149                 public virtual bool HasExplicitParameters {
1150                         get {
1151                                 return true;
1152                         }
1153                 }
1154
1155                 //
1156                 // Returns true if the body of lambda expression can be implicitly
1157                 // converted to the delegate of type `delegate_type'
1158                 //
1159                 public bool ImplicitStandardConversionExists (Type delegate_type)
1160                 {
1161                         EmitContext ec = EmitContext.TempEc;
1162                         using (ec.Set (EmitContext.Flags.ProbingMode)) {
1163                                 return Compatible (ec, delegate_type) != null;
1164                         }
1165                 }
1166
1167                 protected Expression CompatibleChecks (EmitContext ec, Type delegate_type)
1168                 {
1169                         if (!ec.IsAnonymousMethodAllowed) {
1170                                 Report.Error (1706, loc,
1171                                               "Anonymous methods are not allowed in the " +
1172                                               "attribute declaration");
1173                                 return null;
1174                         }
1175                         
1176                         if (!TypeManager.IsDelegateType (delegate_type)){
1177                                 Report.Error (1660, loc,
1178                                               "Cannot convert `{0}' to type " +
1179                                               "`{1}' because it is not a delegate type",
1180                                               GetSignatureForError (), TypeManager.CSharpName (delegate_type));
1181                                 return null;
1182                         }
1183                         return this;
1184                 }
1185
1186                 protected bool VerifyExplicitParameters (Type delegateType, ParameterData parameters, bool ignoreError)
1187                 {
1188                         if (VerifyParameterCompatibility (delegateType, parameters, ignoreError))
1189                                 return true;
1190
1191                         if (!ignoreError)
1192                                 Report.Error (1661, loc,
1193                                         "Cannot convert `{0}' to delegate type `{1}' since there is a parameter mismatch",
1194                                         GetSignatureForError (), TypeManager.CSharpName (delegateType));
1195
1196                         return false;
1197                 }
1198
1199                 protected bool VerifyParameterCompatibility (Type delegate_type, ParameterData invoke_pd, bool ignoreErrors)
1200                 {
1201                         if (Parameters.Count != invoke_pd.Count) {
1202                                 if (ignoreErrors)
1203                                         return false;
1204                                 
1205                                 Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments",
1206                                               TypeManager.CSharpName (delegate_type), Parameters.Count.ToString ());
1207                                 return false;
1208                         }
1209                         
1210                         if (!HasExplicitParameters)
1211                                 return true;                    
1212
1213                         bool error = false;
1214                         for (int i = 0; i < Parameters.Count; ++i) {
1215                                 Parameter.Modifier p_mod = invoke_pd.ParameterModifier (i);
1216                                 if (Parameters.ParameterModifier (i) != p_mod && p_mod != Parameter.Modifier.PARAMS) {
1217                                         if (ignoreErrors)
1218                                                 return false;
1219                                         
1220                                         if (p_mod == Parameter.Modifier.NONE)
1221                                                 Report.Error (1677, loc, "Parameter `{0}' should not be declared with the `{1}' keyword",
1222                                                               (i + 1).ToString (), Parameter.GetModifierSignature (Parameters.ParameterModifier (i)));
1223                                         else
1224                                                 Report.Error (1676, loc, "Parameter `{0}' must be declared with the `{1}' keyword",
1225                                                               (i+1).ToString (), Parameter.GetModifierSignature (p_mod));
1226                                         error = true;
1227                                         continue;
1228                                 }
1229
1230                                 Type type = invoke_pd.Types [i];
1231                                 
1232                                 // We assume that generic parameters are always inflated
1233                                 if (TypeManager.IsGenericParameter (type))
1234                                         continue;
1235                                 
1236                                 if (TypeManager.HasElementType (type) && TypeManager.IsGenericParameter (TypeManager.GetElementType (type)))
1237                                         continue;
1238                                 
1239                                 if (invoke_pd.ParameterType (i) != Parameters.ParameterType (i)) {
1240                                         if (ignoreErrors)
1241                                                 return false;
1242                                         
1243                                         Report.Error (1678, loc, "Parameter `{0}' is declared as type `{1}' but should be `{2}'",
1244                                                       (i+1).ToString (),
1245                                                       TypeManager.CSharpName (Parameters.ParameterType (i)),
1246                                                       TypeManager.CSharpName (invoke_pd.ParameterType (i)));
1247                                         error = true;
1248                                 }
1249                         }
1250
1251                         return !error;
1252                 }
1253
1254                 //
1255                 // Infers type arguments based on explicit arguments
1256                 //
1257                 public bool ExplicitTypeInference (TypeInferenceContext typeInference, Type delegateType)
1258                 {
1259                         if (!HasExplicitParameters)
1260                                 return false;
1261
1262                         if (!TypeManager.IsDelegateType (delegateType))
1263                                 return false;
1264
1265                         ParameterData d_params = TypeManager.GetDelegateParameters (delegateType);
1266                         if (d_params.Count != Parameters.Count)
1267                                 return false;
1268
1269                         for (int i = 0; i < Parameters.Count; ++i) {
1270                                 Type itype = d_params.Types [i];
1271                                 if (!TypeManager.IsGenericParameter (itype)) {
1272                                         if (!itype.HasElementType)
1273                                                 continue;
1274                                         
1275                                         if (!TypeManager.IsGenericParameter (itype.GetElementType ()))
1276                                             continue;
1277                                 }
1278                                 typeInference.ExactInference (Parameters.FixedParameters[i].ParameterType, itype);
1279                         }
1280                         return true;
1281                 }
1282
1283                 public Type InferReturnType (EmitContext ec, TypeInferenceContext tic, Type delegateType)
1284                 {
1285                         AnonymousMethod am;
1286                         using (ec.Set (EmitContext.Flags.ProbingMode | EmitContext.Flags.InferReturnType)) {
1287                                 am = CompatibleMethod (ec, tic, GetType (), delegateType);
1288                         }
1289                         
1290                         if (am == null)
1291                                 return null;
1292
1293                         if (am.ReturnType == TypeManager.null_type)
1294                                 am.ReturnType = null;
1295
1296                         return am.ReturnType;
1297                 }
1298
1299                 //
1300                 // Returns AnonymousMethod container if this anonymous method
1301                 // expression can be implicitly converted to the delegate type `delegate_type'
1302                 //
1303                 public AnonymousMethod Compatible (EmitContext ec, Type delegateType)
1304                 {
1305                         if (CompatibleChecks (ec, delegateType) == null)
1306                                 return null;
1307
1308                         //
1309                         // At this point its the first time we know the return type that is 
1310                         // needed for the anonymous method.  We create the method here.
1311                         //
1312
1313                         MethodInfo invoke_mb = Delegate.GetInvokeMethod (
1314                                 ec.ContainerType, delegateType);
1315                         Type return_type = invoke_mb.ReturnType;
1316
1317 #if MS_COMPATIBLE
1318                         Type[] g_args = delegateType.GetGenericArguments ();
1319                         if (return_type.IsGenericParameter)
1320                                 return_type = g_args [return_type.GenericParameterPosition];
1321 #endif
1322
1323                         //
1324                         // Second: the return type of the delegate must be compatible with 
1325                         // the anonymous type.   Instead of doing a pass to examine the block
1326                         // we satisfy the rule by setting the return type on the EmitContext
1327                         // to be the delegate type return type.
1328                         //
1329
1330                         Report.Debug (64, "COMPATIBLE", this, Parent, GenericMethod, Host,
1331                                       Container, Block, return_type, delegateType,
1332                                       TypeManager.IsGenericType (delegateType), loc);
1333
1334                         try {
1335                                 return CompatibleMethod (ec, null, return_type, delegateType);
1336                         } catch (Exception e) {
1337                                 throw new InternalErrorException (e, loc);
1338                         }
1339                 }
1340
1341                 protected virtual Parameters ResolveParameters (EmitContext ec, TypeInferenceContext tic, Type delegateType)
1342                 {
1343                         ParameterData delegateParameters = TypeManager.GetDelegateParameters (delegateType);
1344
1345                         if (Parameters == null) {
1346                                 //
1347                                 // We provide a set of inaccessible parameters
1348                                 //
1349                                 Parameter[] fixedpars = new Parameter[delegateParameters.Count];
1350
1351                                 for (int i = 0; i < delegateParameters.Count; i++) {
1352                                         Parameter.Modifier i_mod = delegateParameters.ParameterModifier (i);
1353                                         if ((i_mod & Parameter.Modifier.OUTMASK) != 0) {
1354                                                 Report.Error (1688, loc, "Cannot convert anonymous " +
1355                                                                   "method block without a parameter list " +
1356                                                                   "to delegate type `{0}' because it has " +
1357                                                                   "one or more `out' parameters.",
1358                                                                   TypeManager.CSharpName (delegateType));
1359                                                 return null;
1360                                         }
1361                                         fixedpars[i] = new Parameter (
1362                                                 delegateParameters.ParameterType (i), "+" + (++next_index),
1363                                                 delegateParameters.ParameterModifier (i), null, loc);
1364                                 }
1365
1366                                 return Parameters.CreateFullyResolved (fixedpars, delegateParameters.Types);
1367                         }
1368
1369                         if (!VerifyExplicitParameters (delegateType, delegateParameters, ec.IsInProbingMode)) {
1370                                 return null;
1371                         }
1372
1373                         return Parameters;
1374                 }
1375
1376                 public override Expression DoResolve (EmitContext ec)
1377                 {
1378                         //
1379                         // Set class type, set type
1380                         //
1381
1382                         eclass = ExprClass.Value;
1383
1384                         //
1385                         // This hack means `The type is not accessible
1386                         // anywhere', we depend on special conversion
1387                         // rules.
1388                         // 
1389                         type = TypeManager.anonymous_method_type;
1390
1391                         if ((Parameters != null) && !Parameters.Resolve (ec))
1392                                 return null;
1393
1394                         return this;
1395                 }
1396
1397                 public override void Emit (EmitContext ec)
1398                 {
1399                         // nothing, as we only exist to not do anything.
1400                 }
1401
1402                 public override string GetSignatureForError ()
1403                 {
1404                         return ExprClassName;
1405                 }
1406
1407                 public bool IsIterator {
1408                         get { return false; }
1409                 }
1410
1411                 protected AnonymousMethod CompatibleMethod (EmitContext ec, TypeInferenceContext tic, Type returnType, Type delegateType)
1412                 {
1413                         Parameters p = ResolveParameters (ec, tic, delegateType);
1414                         if (p == null)
1415                                 return null;
1416
1417                         ToplevelBlock b = ec.IsInProbingMode ? (ToplevelBlock) Block.PerformClone () : Block;
1418
1419                         AnonymousMethod anonymous = CompatibleMethodFactory (returnType, delegateType, p, b);
1420                         if (!anonymous.Compatible (ec))
1421                                 return null;
1422
1423                         return anonymous;
1424                 }
1425
1426                 protected virtual AnonymousMethod CompatibleMethodFactory (Type returnType, Type delegateType, Parameters p, ToplevelBlock b)
1427                 {
1428                         return new AnonymousMethod (RootScope, Host,
1429                                 GenericMethod, p, Container, b, returnType,
1430                                 delegateType, loc);
1431                 }
1432
1433                 protected override void CloneTo (CloneContext clonectx, Expression t)
1434                 {
1435                         AnonymousMethodExpression target = (AnonymousMethodExpression) t;
1436
1437                         target.Block = (ToplevelBlock) clonectx.LookupBlock (Block);
1438                         target.container = clonectx.LookupBlock (Block);
1439                 }
1440         }
1441
1442         public abstract class AnonymousContainer : IAnonymousContainer
1443         {
1444                 public readonly Location Location;
1445
1446                 public Parameters Parameters;
1447
1448                 //
1449                 // The block that makes up the body for the anonymous mehtod
1450                 //
1451                 public readonly ToplevelBlock Block;
1452
1453                 public readonly int ModFlags;
1454                 public Type ReturnType;
1455                 public readonly DeclSpace Host;
1456
1457                 //
1458                 // The implicit method we create
1459                 //
1460                 protected Method method;
1461                 protected EmitContext aec;
1462
1463                 // The emit context for the anonymous method
1464                 protected bool unreachable;
1465                 protected readonly Block container;
1466                 protected readonly GenericMethod generic;
1467
1468                 protected AnonymousContainer (DeclSpace host,
1469                                               GenericMethod generic, Parameters parameters,
1470                                               Block container, ToplevelBlock block,
1471                                               Type return_type, int mod, Location loc)
1472                 {
1473                         this.ReturnType = return_type;
1474                         this.ModFlags = mod | Modifiers.COMPILER_GENERATED;
1475                         this.Host = host;
1476
1477                         this.container = container;
1478                         this.generic = generic;
1479                         this.Parameters = parameters;
1480                         this.Block = block;
1481                         this.Location = loc;
1482
1483                         block.AnonymousContainer = this;
1484                 }
1485
1486                 public Method Method {
1487                         get { return method; }
1488                 }
1489
1490                 public abstract string ContainerType {
1491                         get; 
1492                 }
1493
1494                 public abstract RootScopeInfo RootScope {
1495                         get;
1496                 }
1497
1498                 public abstract ScopeInfo Scope {
1499                         get;
1500                 }
1501
1502                 public abstract string GetSignatureForError ();
1503
1504                 public bool Compatible (EmitContext ec)
1505                 {
1506                         // REFACTOR: The method should be refactor, many of the
1507                         // hacks can be handled in better way
1508
1509                         Report.Debug (64, "RESOLVE ANONYMOUS METHOD", this, Location, ec,
1510                                       RootScope, Parameters, ec.IsStatic);
1511
1512                         if (ReturnType != null) {
1513                                 TypeExpr return_type_expr;
1514                                 if (RootScope != null)
1515                                         return_type_expr = RootScope.InflateType (ReturnType);
1516                                 else
1517                                         return_type_expr = new TypeExpression (ReturnType, Location);
1518                                 return_type_expr = return_type_expr.ResolveAsTypeTerminal (ec, false);
1519                                 if ((return_type_expr == null) || (return_type_expr.Type == null))
1520                                         return false;
1521                                 ReturnType = return_type_expr.Type;
1522                         }
1523
1524                         // Linq type inference is done differently
1525                         if (RootScope != null && RootContext.Version != LanguageVersion.LINQ)
1526                                 Parameters = RootScope.InflateParameters (Parameters);
1527
1528                         aec = new EmitContext (
1529                                 ec.ResolveContext, ec.TypeContainer,
1530                                 RootScope != null ? RootScope : Host, Location, null, ReturnType,
1531                                 /* REVIEW */ (ec.InIterator ? Modifiers.METHOD_YIELDS : 0) |
1532                                 (ec.InUnsafe ? Modifiers.UNSAFE : 0), /* No constructor */ false);
1533
1534                         aec.CurrentAnonymousMethod = this;
1535                         aec.IsStatic = ec.IsStatic;
1536                         
1537                         //
1538                         // HACK: Overwrite parent declaration container to currently resolved.
1539                         // It's required for an anonymous container inside partial class.
1540                         //
1541                         if (RootScope != null)
1542                                 aec.DeclContainer.Parent = ec.TypeContainer;
1543
1544                         IDisposable aec_dispose = null;
1545                         if (ec.InferReturnType)
1546                                 aec_dispose = aec.Set (EmitContext.Flags.InferReturnType);
1547                         if (ec.IsInProbingMode)
1548                                 aec_dispose = aec.Set (EmitContext.Flags.ProbingMode);
1549                         if (ec.IsInFieldInitializer)
1550                                 aec_dispose = aec.Set (EmitContext.Flags.InFieldInitializer);
1551
1552                         Report.Debug (64, "RESOLVE ANONYMOUS METHOD #1", this, Location, ec, aec,
1553                                       RootScope, Parameters, Block);
1554
1555                         bool unreachable;
1556                         bool res = aec.ResolveTopBlock (ec, Block, Parameters, null, out unreachable);
1557
1558                         if (ec.InferReturnType)
1559                                 ReturnType = aec.ReturnType;
1560
1561                         if (aec_dispose != null) {
1562                                 aec_dispose.Dispose ();
1563                         }
1564
1565                         return res;
1566                 }
1567
1568                 public abstract Expression Resolve (EmitContext ec);
1569
1570                 public virtual bool Define (EmitContext ec)
1571                 {
1572                         Report.Debug (64, "DEFINE ANONYMOUS METHOD #3", this, ec, aec, Block);
1573
1574                         if (aec == null && !Compatible (ec))
1575                                 return false;
1576
1577                         // Don't define anything when we are in probing scope (nested anonymous methods)
1578                         if (ec.IsInProbingMode)
1579                                 return true;
1580
1581                         method = DoCreateMethodHost (ec);
1582
1583                         if (Scope != null)
1584                                 return true;
1585
1586                         if (!method.ResolveMembers ())
1587                                 return false;
1588                         return method.Define ();
1589                 }
1590
1591                 protected abstract Method DoCreateMethodHost (EmitContext ec);
1592
1593                 public Block Container {
1594                         get { return container; }
1595                 }
1596
1597                 public GenericMethod GenericMethod {
1598                         get { return generic; }
1599                 }
1600
1601                 public abstract bool IsIterator {
1602                         get;
1603                 }
1604
1605                 protected class AnonymousMethodMethod : Method
1606                 {
1607                         public readonly AnonymousContainer AnonymousMethod;
1608                         public readonly ScopeInfo Scope;
1609
1610                         public AnonymousMethodMethod (AnonymousContainer am, ScopeInfo scope,
1611                                                       GenericMethod generic, TypeExpr return_type,
1612                                                       int mod, MemberName name, Parameters parameters)
1613                                 : base (scope != null ? scope : am.Host,
1614                                         generic, return_type, mod | Modifiers.COMPILER_GENERATED, false, name, parameters, null)
1615                         {
1616                                 this.AnonymousMethod = am;
1617                                 this.Scope = scope;
1618
1619                                 if (scope != null) {
1620                                         scope.CheckMembersDefined ();
1621                                         scope.AddMethod (this);
1622                                 } else {
1623                                         ModFlags |= Modifiers.STATIC;
1624                                         am.Host.PartialContainer.AddMethod (this);
1625                                 }
1626                                 Block = am.Block;
1627                         }
1628
1629                         public override EmitContext CreateEmitContext (DeclSpace tc, ILGenerator ig)
1630                         {
1631                                 EmitContext aec = AnonymousMethod.aec;
1632                                 aec.ig = ig;
1633                                 aec.MethodIsStatic = Scope == null;
1634                                 return aec;
1635                         }
1636                 }
1637         }
1638
1639         public class AnonymousMethod : AnonymousContainer
1640         {
1641                 Type DelegateType;
1642
1643                 //
1644                 // The value return by the Compatible call, this ensure that
1645                 // the code works even if invoked more than once (Resolve called
1646                 // more than once, due to the way Convert.ImplicitConversion works
1647                 //
1648                 RootScopeInfo root_scope;
1649                 ScopeInfo scope;
1650
1651                 public AnonymousMethod (RootScopeInfo root_scope,
1652                                         DeclSpace host, GenericMethod generic,
1653                                         Parameters parameters, Block container,
1654                                         ToplevelBlock block, Type return_type, Type delegate_type,
1655                                         Location loc)
1656                         : base (host, generic, parameters, container, block,
1657                                 return_type, 0, loc)
1658                 {
1659                         this.DelegateType = delegate_type;
1660                         this.root_scope = root_scope;
1661                 }
1662
1663                 public override string ContainerType {
1664                         get { return "anonymous method"; }
1665                 }
1666
1667                 public override RootScopeInfo RootScope {
1668                         get { return root_scope; }
1669                 }
1670
1671                 public override ScopeInfo Scope {
1672                         get { return scope; }
1673                 }
1674
1675                 public override bool IsIterator {
1676                         get { return false; }
1677                 }
1678
1679                 public override string GetSignatureForError ()
1680                 {
1681                         return TypeManager.CSharpName (DelegateType);
1682                 }
1683
1684                 //
1685                 // Creates the host for the anonymous method
1686                 //
1687                 protected override Method DoCreateMethodHost (EmitContext ec)
1688                 {
1689                         MemberCore mc = ec.ResolveContext as MemberCore;
1690                         string name = CompilerGeneratedClass.MakeName (mc.Name, null);
1691                         MemberName member_name;
1692
1693                         Report.Debug (128, "CREATE METHOD HOST #0", RootScope);
1694
1695                         Block b;
1696                         scope = RootScope;
1697
1698                         Report.Debug (128, "CREATE METHOD HOST #1", this, Block, Block.ScopeInfo,
1699                                       RootScope, Location);
1700
1701                         for (b = Block.Parent; b != null; b = b.Parent) {
1702                                 Report.Debug (128, "CREATE METHOD HOST #2", this, Block,
1703                                               b, b.ScopeInfo);
1704                                 if (b.ScopeInfo != null) {
1705                                         scope = b.ScopeInfo;
1706                                         break;
1707                                 }
1708                         }
1709
1710                         if (scope != null)
1711                                 scope.CheckMembersDefined ();
1712
1713                         ArrayList scopes = new ArrayList ();
1714                         if (b != null) {
1715                                 for (b = b.Parent; b != null; b = b.Parent) {
1716                                         if (b.ScopeInfo != null)
1717                                                 scopes.Add (b.ScopeInfo);
1718                                 }
1719                         }
1720
1721                         Report.Debug (128, "CREATE METHOD HOST #1", this, scope, scopes);
1722
1723                         foreach (ScopeInfo si in scopes)
1724                                 scope.CaptureScope (si);
1725
1726                         Report.Debug (128, "CREATE METHOD HOST", this, Block, container,
1727                                       RootScope, scope, scopes, Location);
1728
1729                         GenericMethod generic_method = null;
1730 #if GMCS_SOURCE
1731                         if (TypeManager.IsGenericType (DelegateType)) {
1732                                 TypeArguments args = new TypeArguments (Location);
1733
1734                                 Type dt = DelegateType.GetGenericTypeDefinition ();
1735
1736                                 Type[] tparam = TypeManager.GetTypeArguments (dt);
1737                                 for (int i = 0; i < tparam.Length; i++)
1738                                         args.Add (new SimpleName (tparam [i].Name, Location));
1739
1740                                 member_name = new MemberName (name, args, Location);
1741
1742                                 Report.Debug (128, "CREATE METHOD HOST #5", this, DelegateType,
1743                                               TypeManager.GetTypeArguments (DelegateType),
1744                                               dt, tparam, args);
1745
1746                                 generic_method = new GenericMethod (
1747                                         Host.NamespaceEntry, scope, member_name,
1748                                         new TypeExpression (ReturnType, Location), Parameters);
1749
1750                                 generic_method.SetParameterInfo (null);
1751                         } else
1752 #endif
1753                                 member_name = new MemberName (name, Location);
1754
1755                         return new AnonymousMethodMethod (
1756                                 this, scope, generic_method, new TypeExpression (ReturnType, Location),
1757                                 scope == null ? Modifiers.PRIVATE : Modifiers.INTERNAL, member_name, Parameters);
1758                 }
1759
1760                 public override Expression Resolve (EmitContext ec)
1761                 {
1762                         if (!Define (ec))
1763                                 return null;
1764
1765                         return new AnonymousDelegate (this, DelegateType, Location).Resolve (ec);
1766                 }
1767
1768                 public MethodInfo GetMethodBuilder (EmitContext ec)
1769                 {
1770                         MethodInfo builder = method.MethodBuilder;
1771                         if ((Scope != null) && Scope.IsGeneric) {
1772                                 Type scope_type = Scope.GetScopeType (ec);
1773                                 if (scope_type == null)
1774                                         throw new InternalErrorException ();
1775
1776                                 MethodGroupExpr mg = (MethodGroupExpr) Expression.MemberLookup (
1777                                         ec.ContainerType, scope_type, builder.Name,
1778                                         MemberTypes.Method, Expression.AllBindingFlags | BindingFlags.NonPublic, Location);
1779                                 
1780                                 if (mg == null)
1781                                         throw new InternalErrorException ();
1782                                 builder = (MethodInfo) mg.Methods [0];
1783                         }
1784
1785 #if GMCS_SOURCE
1786                         if (!DelegateType.IsGenericType)
1787                                 return builder;
1788
1789                         Type[] targs = TypeManager.GetTypeArguments (DelegateType);
1790                         return builder.MakeGenericMethod (targs);
1791 #else
1792                         return builder;
1793 #endif
1794                 }
1795
1796                 public static void Error_AddressOfCapturedVar (string name, Location loc)
1797                 {
1798                         Report.Error (1686, loc,
1799                                       "Local variable `{0}' or its members cannot have their " +
1800                                       "address taken and be used inside an anonymous method block",
1801                                       name);
1802                 }
1803         }
1804
1805         //
1806         // This will emit the code for the delegate, as well delegate creation on the host
1807         //
1808         public class AnonymousDelegate : DelegateCreation {
1809                 readonly AnonymousMethod am;
1810
1811                 //
1812                 // if target_type is null, this means that we do not know the type
1813                 // for this delegate, and we want to infer it from the various 
1814                 // returns (implicit and explicit) from the body of this anonymous
1815                 // method.
1816                 //
1817                 // for example, the lambda: x => 1
1818                 //
1819                 public AnonymousDelegate (AnonymousMethod am, Type target_type, Location l)
1820                 {
1821                         type = target_type;
1822                         loc = l;
1823                         this.am = am;
1824                 }
1825
1826                 public override Expression DoResolve (EmitContext ec)
1827                 {
1828                         eclass = ExprClass.Value;
1829                         return this;
1830                 }
1831                 
1832                 public override void Emit (EmitContext ec)
1833                 {
1834                         //ec.ig.Emit (OpCodes.Ldstr, "EMIT ANONYMOUS DELEGATE");
1835                         //ec.ig.Emit (OpCodes.Pop);
1836
1837                         //
1838                         // Now emit the delegate creation.
1839                         //
1840                         if ((am.Method.ModFlags & Modifiers.STATIC) == 0) {
1841                                 Report.Debug (128, "EMIT ANONYMOUS DELEGATE", this, am, am.Scope, loc);
1842                                 delegate_instance_expression = am.Scope.GetScopeInitializer (ec);
1843
1844                                 if (delegate_instance_expression == null)
1845                                         throw new InternalErrorException ();
1846                         }
1847
1848                         constructor_method = Delegate.GetConstructor (ec.ContainerType, type);
1849 #if MS_COMPATIBLE
1850                         if (type.IsGenericType && type is TypeBuilder)
1851                                 constructor_method = TypeBuilder.GetConstructor (type, (ConstructorInfo)constructor_method);
1852 #endif
1853                         
1854                         delegate_method = am.GetMethodBuilder (ec);
1855                         base.Emit (ec);
1856
1857                         //ec.ig.Emit (OpCodes.Ldstr, "EMIT ANONYMOUS DELEGATE DONE");
1858                         //ec.ig.Emit (OpCodes.Pop);
1859
1860                         Report.Debug (128, "EMIT ANONYMOUS DELEGATE DONE", this, am, am.Scope, loc);
1861                 }
1862         }
1863
1864         //
1865         // Anonymous type container
1866         //
1867         public class AnonymousTypeClass : CompilerGeneratedClass
1868         {
1869                 static int types_counter;
1870                 public const string ClassNamePrefix = "<>__AnonType";
1871                 public const string SignatureForError = "anonymous type";
1872                 
1873                 static readonly IntConstant FNV_prime = new IntConstant (16777619, Location.Null);
1874
1875                 readonly ArrayList parameters;
1876
1877                 private AnonymousTypeClass (DeclSpace parent, MemberName name, ArrayList parameters, Location loc)
1878                         : base (parent, name, Modifiers.SEALED, loc)
1879                 {
1880                         this.parameters = parameters;
1881                 }
1882
1883                 public static AnonymousTypeClass Create (TypeContainer parent, ArrayList parameters, Location loc)
1884                 {
1885                         if (RootContext.Version <= LanguageVersion.ISO_2)
1886                                 Report.FeatureIsNotISO1 (loc, "anonymous types");
1887                         
1888                         string name = ClassNamePrefix + types_counter++;
1889
1890                         SimpleName [] t_args = new SimpleName [parameters.Count];
1891                         Parameter [] ctor_params = new Parameter [parameters.Count];
1892                         for (int i = 0; i < parameters.Count; ++i) {
1893                                 AnonymousTypeParameter p = (AnonymousTypeParameter) parameters [i];
1894
1895                                 t_args [i] = new SimpleName ("<" + p.Name + ">__T", p.Location);
1896                                 ctor_params [i] = new Parameter (t_args [i], p.Name, 0, null, p.Location);
1897                         }
1898
1899                         //
1900                         // Create generic anonymous type host with generic arguments
1901                         // named upon properties names
1902                         //
1903                         AnonymousTypeClass a_type = new AnonymousTypeClass (parent.NamespaceEntry.SlaveDeclSpace,
1904                                 new MemberName (name, new TypeArguments (loc, t_args), loc), parameters, loc);
1905
1906                         if (parameters.Count > 0)
1907                                 a_type.SetParameterInfo (null);
1908
1909                         Constructor c = new Constructor (a_type, name, Modifiers.PUBLIC,
1910                                 new Parameters (ctor_params), null, loc);
1911                         c.OptAttributes = a_type.GetDebuggerHiddenAttribute ();
1912                         c.Block = new ToplevelBlock (c.Parameters, loc);
1913
1914                         // 
1915                         // Create fields and contructor body with field initialization
1916                         //
1917                         bool error = false;
1918                         for (int i = 0; i < parameters.Count; ++i) {
1919                                 AnonymousTypeParameter p = (AnonymousTypeParameter) parameters [i];
1920
1921                                 Field f = new Field (a_type, t_args [i], Modifiers.PRIVATE | Modifiers.READONLY,
1922                                         "<" + p.Name + ">", null, p.Location);
1923
1924                                 if (!a_type.AddField (f)) {
1925                                         error = true;
1926                                         Report.Error (833, p.Location, "`{0}': An anonymous type cannot have multiple properties with the same name",
1927                                                 p.Name);
1928                                         continue;
1929                                 }
1930
1931                                 c.Block.AddStatement (new StatementExpression (
1932                                         new Assign (new MemberAccess (new This (p.Location), f.Name),
1933                                                 c.Block.GetParameterReference (p.Name, p.Location))));
1934
1935                                 ToplevelBlock get_block = new ToplevelBlock (p.Location);
1936                                 get_block.AddStatement (new Return (
1937                                         new MemberAccess (new This (p.Location), f.Name), p.Location));
1938                                 Accessor get_accessor = new Accessor (get_block, 0, null, p.Location);
1939                                 Property prop = new Property (a_type, t_args [i], Modifiers.PUBLIC, false,
1940                                         new MemberName (p.Name, p.Location), null, get_accessor, null, false);
1941                                 a_type.AddProperty (prop);
1942                         }
1943
1944                         if (error)
1945                                 return null;
1946
1947                         a_type.AddConstructor (c);
1948                         return a_type;
1949                 }
1950
1951                 protected override bool AddToContainer (MemberCore symbol, string name)
1952                 {
1953                         MemberCore mc = (MemberCore) defined_names [name];
1954
1955                         if (mc == null) {
1956                                 defined_names.Add (name, symbol);
1957                                 return true;
1958                         }
1959
1960                         Report.SymbolRelatedToPreviousError (mc);
1961                         return false;
1962                 }
1963
1964                 void DefineOverrides ()
1965                 {
1966                         Location loc = Location;
1967
1968                         Method equals = new Method (this, null, TypeManager.system_boolean_expr,
1969                                 Modifiers.PUBLIC | Modifiers.OVERRIDE, false, new MemberName ("Equals", loc),
1970                                 new Parameters (new Parameter (TypeManager.system_object_expr, "obj", 0, null, loc)),
1971                                 GetDebuggerHiddenAttribute ());
1972
1973                         Method tostring = new Method (this, null, TypeManager.system_string_expr,
1974                                 Modifiers.PUBLIC | Modifiers.OVERRIDE, false, new MemberName ("ToString", loc),
1975                                 Mono.CSharp.Parameters.EmptyReadOnlyParameters, GetDebuggerHiddenAttribute ());
1976
1977                         ToplevelBlock equals_block = new ToplevelBlock (equals.Parameters, loc);
1978                         TypeExpr current_type;
1979                         if (IsGeneric)
1980                                 current_type = new ConstructedType (TypeBuilder, TypeParameters, loc);
1981                         else
1982                                 current_type = new TypeExpression (TypeBuilder, loc);
1983
1984                         equals_block.AddVariable (current_type, "other", loc);
1985                         LocalVariableReference other_variable = new LocalVariableReference (equals_block, "other", loc);
1986
1987                         MemberAccess system_collections_generic = new MemberAccess (new MemberAccess (
1988                                 new SimpleName ("System", loc), "Collections", loc), "Generic", loc);
1989
1990                         Expression rs_equals = null;
1991                         Expression string_concat = new StringConstant ("<empty type>", loc);
1992                         Expression rs_hashcode = new IntConstant (-2128831035, loc);
1993                         for (int i = 0; i < parameters.Count; ++i) {
1994                                 AnonymousTypeParameter p = (AnonymousTypeParameter) parameters [i];
1995                                 Field f = (Field) Fields [i];
1996
1997                                 MemberAccess equality_comparer = new MemberAccess (new MemberAccess (
1998                                         system_collections_generic, "EqualityComparer",
1999                                                 new TypeArguments (loc, new SimpleName (TypeParameters [i].Name, loc)), loc),
2000                                                 "Default", loc);
2001
2002                                 ArrayList arguments_equal = new ArrayList (2);
2003                                 arguments_equal.Add (new Argument (new MemberAccess (new This (f.Location), f.Name)));
2004                                 arguments_equal.Add (new Argument (new MemberAccess (other_variable, f.Name)));
2005
2006                                 Expression field_equal = new Invocation (new MemberAccess (equality_comparer,
2007                                         "Equals", loc), arguments_equal);
2008
2009                                 ArrayList arguments_hashcode = new ArrayList (1);
2010                                 arguments_hashcode.Add (new Argument (new MemberAccess (new This (f.Location), f.Name)));
2011                                 Expression field_hashcode = new Invocation (new MemberAccess (equality_comparer,
2012                                         "GetHashCode", loc), arguments_hashcode);
2013
2014                                 rs_hashcode = new Binary (Binary.Operator.Multiply,
2015                                         new Binary (Binary.Operator.ExclusiveOr, rs_hashcode, field_hashcode),
2016                                         FNV_prime);
2017
2018                                 Expression field_to_string = new Conditional (new Binary (Binary.Operator.Inequality,
2019                                         new MemberAccess (new This (f.Location), f.Name), new NullConstant (loc)),
2020                                         new Invocation (new MemberAccess (
2021                                                 new MemberAccess (new This (f.Location), f.Name), "ToString"), null),
2022                                         new StringConstant ("<null>", loc));
2023
2024                                 if (rs_equals == null) {
2025                                         rs_equals = field_equal;
2026                                         string_concat = new Binary (Binary.Operator.Addition,
2027                                                 new StringConstant (p.Name + " = ", loc),
2028                                                 field_to_string);
2029                                         continue;
2030                                 }
2031
2032                                 //
2033                                 // Implementation of ToString () body using string concatenation
2034                                 //                              
2035                                 string_concat = new Binary (Binary.Operator.Addition,
2036                                         new Binary (Binary.Operator.Addition,
2037                                                 string_concat,
2038                                                 new StringConstant (", " + p.Name + " = ", loc)),
2039                                         field_to_string);
2040
2041                                 rs_equals = new Binary (Binary.Operator.LogicalAnd, rs_equals, field_equal);
2042                         }
2043
2044                         //
2045                         // Equals (object obj) override
2046                         //
2047                         equals_block.AddStatement (new StatementExpression (
2048                                 new Assign (other_variable,
2049                                         new As (equals_block.GetParameterReference ("obj", loc),
2050                                                 current_type, loc), loc)));
2051
2052                         Expression equals_test = new Binary (Binary.Operator.Inequality, other_variable, new NullLiteral (loc));
2053                         if (rs_equals != null)
2054                                 equals_test = new Binary (Binary.Operator.LogicalAnd, equals_test, rs_equals);
2055                         equals_block.AddStatement (new Return (equals_test, loc));
2056
2057                         equals.Block = equals_block;
2058                         equals.ResolveMembers ();
2059                         AddMethod (equals);
2060
2061                         //
2062                         // GetHashCode () override
2063                         //
2064                         Method hashcode = new Method (this, null, TypeManager.system_int32_expr,
2065                                 Modifiers.PUBLIC | Modifiers.OVERRIDE, false, new MemberName ("GetHashCode", loc),
2066                                 Mono.CSharp.Parameters.EmptyReadOnlyParameters, GetDebuggerHiddenAttribute ());
2067
2068                         //
2069                         // Modified FNV with good avalanche behavior and uniform
2070                         // distribution with larger hash sizes.
2071                         //
2072                         // const int FNV_prime = 16777619;
2073                         // int hash = (int) 2166136261;
2074                         // foreach (int d in data)
2075                         //     hash = (hash ^ d) * FNV_prime;
2076                         // hash += hash << 13;
2077                         // hash ^= hash >> 7;
2078                         // hash += hash << 3;
2079                         // hash ^= hash >> 17;
2080                         // hash += hash << 5;
2081
2082                         ToplevelBlock hashcode_block = new ToplevelBlock (loc);
2083                         hashcode_block.AddVariable (TypeManager.system_int32_expr, "hash", loc);
2084                         LocalVariableReference hash_variable = new LocalVariableReference (hashcode_block, "hash", loc);
2085                         hashcode_block.AddStatement (new StatementExpression (
2086                                 new Assign (hash_variable, rs_hashcode)));
2087
2088                         hashcode_block.AddStatement (new StatementExpression (
2089                                 new CompoundAssign (Binary.Operator.Addition, hash_variable,
2090                                         new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (13, loc)))));
2091                         hashcode_block.AddStatement (new StatementExpression (
2092                                 new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable,
2093                                         new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (7, loc)))));
2094                         hashcode_block.AddStatement (new StatementExpression (
2095                                 new CompoundAssign (Binary.Operator.Addition, hash_variable,
2096                                         new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (3, loc)))));
2097                         hashcode_block.AddStatement (new StatementExpression (
2098                                 new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable,
2099                                         new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (17, loc)))));
2100                         hashcode_block.AddStatement (new StatementExpression (
2101                                 new CompoundAssign (Binary.Operator.Addition, hash_variable,
2102                                         new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (5, loc)))));
2103
2104                         hashcode_block.AddStatement (new Return (hash_variable, loc));
2105                         hashcode.Block = hashcode_block;
2106                         hashcode.ResolveMembers ();
2107                         AddMethod (hashcode);
2108
2109                         //
2110                         // ToString () override
2111                         //
2112
2113                         ToplevelBlock tostring_block = new ToplevelBlock (loc);
2114                         tostring_block.AddStatement (new Return (string_concat, loc));
2115                         tostring.Block = tostring_block;
2116                         tostring.ResolveMembers ();
2117                         AddMethod (tostring);
2118                 }
2119
2120                 public override bool DefineMembers ()
2121                 {
2122                         DefineOverrides ();
2123
2124                         return base.DefineMembers ();
2125                 }
2126
2127                 Attributes GetDebuggerHiddenAttribute ()
2128                 {
2129                         return new Attributes (new Attribute (null, null,
2130                                 "System.Diagnostics.DebuggerHiddenAttribute", null, Location, false));
2131                 }
2132
2133                 public override string GetSignatureForError ()
2134                 {
2135                         return SignatureForError;
2136                 }
2137
2138                 public ArrayList Parameters {
2139                         get {
2140                                 return parameters;
2141                         }
2142                 }
2143         }
2144 }