Wed Feb 24 15:47:16 CET 2010 Paolo Molaro <lupus@ximian.com>
[mono.git] / mcs / mcs / anonymous.cs
1 //
2 // anonymous.cs: Support for anonymous methods and types
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximain.com)
6 //   Marek Safar (marek.safar@gmail.com)
7 //
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
9 // Copyright 2003-2008 Novell, Inc.
10 //
11
12 using System;
13 using System.Text;
14 using System.Collections.Generic;
15 using System.Reflection;
16 using System.Reflection.Emit;
17
18 namespace Mono.CSharp {
19
20         public abstract class CompilerGeneratedClass : Class
21         {
22                 public static string MakeName (string host, string typePrefix, string name, int id)
23                 {
24                         return "<" + host + ">" + typePrefix + "__" + name + id.ToString ("X");
25                 }
26                 
27                 protected CompilerGeneratedClass (DeclSpace parent, MemberName name, Modifiers mod)
28                         : base (parent.NamespaceEntry, parent, name, mod | Modifiers.COMPILER_GENERATED | Modifiers.SEALED, null)
29                 {
30                 }
31
32                 protected CompilerGeneratedClass (DeclSpace parent, GenericMethod generic, MemberName name, Modifiers mod)
33                         : this (parent, name, mod)
34                 {
35                         if (generic != null) {
36                                 var list = new List<Constraints> ();
37                                 foreach (TypeParameter tparam in generic.TypeParameters) {
38                                         if (tparam.Constraints != null)
39                                                 list.Add (tparam.Constraints.Clone ());
40                                 }
41                                 SetParameterInfo (list);
42                         }
43                 }
44
45                 protected void CheckMembersDefined ()
46                 {
47                         if (members_defined)
48                                 throw new InternalErrorException ("Helper class already defined!");
49                 }
50         }
51
52         //
53         // Anonymous method storey is created when an anonymous method uses
54         // variable or parameter from outer scope. They are then hoisted to
55         // anonymous method storey (captured)
56         //
57         public class AnonymousMethodStorey : CompilerGeneratedClass
58         {
59                 struct StoreyFieldPair
60                 {
61                         public readonly AnonymousMethodStorey Storey;
62                         public readonly Field Field;
63
64                         public StoreyFieldPair (AnonymousMethodStorey storey, Field field)
65                         {
66                                 this.Storey = storey;
67                                 this.Field = field;
68                         }
69                 }
70
71                 sealed class HoistedGenericField : Field
72                 {
73                         public HoistedGenericField (DeclSpace parent, FullNamedExpression type, Modifiers mod, string name,
74                                   Attributes attrs, Location loc)
75                                 : base (parent, type, mod, new MemberName (name, loc), attrs)
76                         {
77                         }
78
79                         protected override bool ResolveMemberType ()
80                         {
81                                 if (!base.ResolveMemberType ())
82                                         return false;
83
84                                 AnonymousMethodStorey parent = ((AnonymousMethodStorey) Parent).GetGenericStorey ();
85                                 if (parent != null)
86                                         member_type = parent.MutateType (MemberType);
87
88                                 return true;
89                         }
90                 }
91
92                 //
93                 // Needed to delay hoisted _this_ initialization. When an anonymous
94                 // method is used inside ctor and _this_ is hoisted, base ctor has to
95                 // be called first, otherwise _this_ will be initialized with 
96                 // uninitialized value.
97                 //
98                 sealed class ThisInitializer : Statement
99                 {
100                         readonly HoistedThis hoisted_this;
101
102                         public ThisInitializer (HoistedThis hoisted_this)
103                         {
104                                 this.hoisted_this = hoisted_this;
105                         }
106
107                         protected override void DoEmit (EmitContext ec)
108                         {
109                                 hoisted_this.EmitHoistingAssignment (ec);
110                         }
111
112                         protected override void CloneTo (CloneContext clonectx, Statement target)
113                         {
114                                 // Nothing to clone
115                         }
116
117                         public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
118                         {
119                                 // Nothing to mutate
120                         }
121                 }
122
123                 // Unique storey ID
124                 public readonly int ID;
125                 static int unique_id;
126
127                 public readonly Block OriginalSourceBlock;
128
129                 // A list of StoreyFieldPair with local field keeping parent storey instance
130                 List<StoreyFieldPair> used_parent_storeys;
131                 List<ExplicitBlock> children_references;
132
133                 // A list of hoisted parameters
134                 protected List<HoistedParameter> hoisted_params;
135                 protected List<HoistedVariable> hoisted_locals;
136
137                 // Hoisted this
138                 protected HoistedThis hoisted_this;
139
140                 // Local variable which holds this storey instance
141                 public LocalTemporary Instance;
142
143                 public AnonymousMethodStorey (Block block, TypeContainer parent, MemberBase host, GenericMethod generic, string name)
144                         : base (parent, generic, MakeMemberName (host, name, generic, block.StartLocation), Modifiers.PRIVATE)
145                 {
146                         Parent = parent;
147                         OriginalSourceBlock = block;
148                         ID = unique_id++;
149                 }
150
151                 static MemberName MakeMemberName (MemberBase host, string name, GenericMethod generic, Location loc)
152                 {
153                         string host_name = host == null ? null : host.Name;
154                         string tname = MakeName (host_name, "c", name, unique_id);
155                         TypeArguments args = null;
156                         if (generic != null) {
157                                 args = new TypeArguments ();
158                                 foreach (TypeParameter tparam in generic.CurrentTypeParameters)
159                                         args.Add (new TypeParameterName (tparam.Name, null, loc));
160                         }
161
162                         return new MemberName (tname, args, loc);
163                 }
164
165                 public void AddCapturedThisField (EmitContext ec)
166                 {
167                         TypeExpr type_expr = new TypeExpression (ec.CurrentType, Location);
168                         Field f = AddCompilerGeneratedField ("<>f__this", type_expr);
169                         f.Define ();
170                         hoisted_this = new HoistedThis (this, f);
171                 }
172
173                 public Field AddCapturedVariable (string name, Type type)
174                 {
175                         CheckMembersDefined ();
176
177                         FullNamedExpression field_type = new TypeExpression (type, Location);
178                         if (!IsGeneric)
179                                 return AddCompilerGeneratedField (name, field_type);
180
181                         const Modifiers mod = Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED;
182                         Field f = new HoistedGenericField (this, field_type, mod, name, null, Location);
183                         AddField (f);
184                         return f;
185                 }
186
187                 protected Field AddCompilerGeneratedField (string name, FullNamedExpression type)
188                 {
189                         const Modifiers mod = Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED;
190                         Field f = new Field (this, type, mod, new MemberName (name, Location), null);
191                         AddField (f);
192                         return f;
193                 }
194
195                 //
196                 // Creates a link between block and the anonymous method storey
197                 //
198                 // An anonymous method can reference variables from any outer block, but they are
199                 // hoisted in their own ExplicitBlock. When more than one block is referenced we
200                 // need to create another link between those variable storeys
201                 //
202                 public void AddReferenceFromChildrenBlock (ExplicitBlock block)
203                 {
204                         if (children_references == null)
205                                 children_references = new List<ExplicitBlock> ();
206
207                         if (!children_references.Contains (block))
208                                 children_references.Add (block);
209                 }
210
211                 public void AddParentStoreyReference (AnonymousMethodStorey storey)
212                 {
213                         CheckMembersDefined ();
214
215                         if (used_parent_storeys == null)
216                                 used_parent_storeys = new List<StoreyFieldPair> ();
217                         else if (used_parent_storeys.Exists (i => i.Storey == storey))
218                                 return;
219
220                         TypeExpr type_expr = new TypeExpression (storey.TypeBuilder, Location);
221                         Field f = AddCompilerGeneratedField ("<>f__ref$" + storey.ID, type_expr);
222                         used_parent_storeys.Add (new StoreyFieldPair (storey, f));
223                 }
224
225                 public void CaptureLocalVariable (ResolveContext ec, LocalInfo local_info)
226                 {
227                         ec.CurrentBlock.Explicit.HasCapturedVariable = true;
228                         if (ec.CurrentBlock.Explicit != local_info.Block.Explicit)
229                                 AddReferenceFromChildrenBlock (ec.CurrentBlock.Explicit);
230
231                         if (local_info.HoistedVariant != null)
232                                 return;
233
234                         HoistedVariable var = new HoistedLocalVariable (this, local_info, GetVariableMangledName (local_info));
235                         local_info.HoistedVariant = var;
236
237                         if (hoisted_locals == null)
238                                 hoisted_locals = new List<HoistedVariable> ();
239
240                         hoisted_locals.Add (var);
241                 }
242
243                 public void CaptureParameter (ResolveContext ec, ParameterReference param_ref)
244                 {
245                         ec.CurrentBlock.Explicit.HasCapturedVariable = true;
246                         AddReferenceFromChildrenBlock (ec.CurrentBlock.Explicit);
247
248                         if (param_ref.GetHoistedVariable (ec) != null)
249                                 return;
250
251                         if (hoisted_params == null)
252                                 hoisted_params = new List<HoistedParameter> (2);
253
254                         var expr = new HoistedParameter (this, param_ref);
255                         param_ref.Parameter.HoistedVariant = expr;
256                         hoisted_params.Add (expr);
257                 }
258
259                 public void ChangeParentStorey (AnonymousMethodStorey parentStorey)
260                 {
261                         Parent = parentStorey;
262                         type_params = null;
263                 }
264
265                 //
266                 // Initializes all hoisted variables
267                 //
268                 public void EmitStoreyInstantiation (EmitContext ec)
269                 {
270                         // There can be only one instance variable for each storey type
271                         if (Instance != null)
272                                 throw new InternalErrorException ();
273
274                         SymbolWriter.OpenCompilerGeneratedBlock (ec.ig);
275
276                         //
277                         // Create an instance of storey type
278                         //
279                         Expression storey_type_expr;
280                         if (is_generic) {
281                                 //
282                                 // Use current method type parameter (MVAR) for top level storey only. All
283                                 // nested storeys use class type parameter (VAR)
284                                 //
285                                 TypeParameter[] tparams = ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.Storey != null ?
286                                         ec.CurrentAnonymousMethod.Storey.TypeParameters :
287                                         ec.CurrentTypeParameters;
288
289                                 TypeArguments targs = new TypeArguments ();
290
291                                 if (tparams.Length < CountTypeParameters) {
292                                         TypeParameter[] parent_tparams = ec.MemberContext.CurrentTypeDefinition.TypeParameters;
293                                         for (int i = 0; i < parent_tparams.Length; ++i)
294                                                 targs.Add (new TypeParameterExpr (parent_tparams[i], Location));
295                                 }
296                                 
297                                 for (int i = 0; i < tparams.Length; ++i)
298                                         targs.Add (new TypeParameterExpr (tparams[i], Location));
299
300                                 storey_type_expr = new GenericTypeExpr (TypeBuilder, targs, Location);
301                         } else {
302                                 storey_type_expr = new TypeExpression (TypeBuilder, Location);
303                         }
304
305                         ResolveContext rc = new ResolveContext (this);
306                         Expression e = new New (storey_type_expr, null, Location).Resolve (rc);
307                         e.Emit (ec);
308
309                         Instance = new LocalTemporary (storey_type_expr.Type);
310                         Instance.Store (ec);
311
312                         EmitHoistedFieldsInitialization (ec);
313
314                         SymbolWriter.DefineScopeVariable (ID, Instance.Builder);
315                         SymbolWriter.CloseCompilerGeneratedBlock (ec.ig);
316                 }
317
318                 void EmitHoistedFieldsInitialization (EmitContext ec)
319                 {
320                         //
321                         // Initialize all storey reference fields by using local or hoisted variables
322                         //
323                         if (used_parent_storeys != null) {
324                                 foreach (StoreyFieldPair sf in used_parent_storeys) {
325                                         //
326                                         // Setting local field
327                                         //
328                                         Expression instace_expr = GetStoreyInstanceExpression (ec);
329                                         FieldExpr f_set_expr = TypeManager.IsGenericType (instace_expr.Type) ?
330                                                 new FieldExpr (sf.Field, instace_expr.Type, Location) :
331                                                 new FieldExpr (sf.Field, Location);
332                                         f_set_expr.InstanceExpression = instace_expr;
333
334                                         SimpleAssign a = new SimpleAssign (f_set_expr, sf.Storey.GetStoreyInstanceExpression (ec));
335                                         if (a.Resolve (new ResolveContext (ec.MemberContext)) != null)
336                                                 a.EmitStatement (ec);
337                                 }
338                         }
339
340                         //
341                         // Define hoisted `this' in top-level storey only 
342                         //
343                         if (OriginalSourceBlock.Explicit.HasCapturedThis && !(Parent is AnonymousMethodStorey)) {
344                                 AddCapturedThisField (ec);
345                                 OriginalSourceBlock.AddScopeStatement (new ThisInitializer (hoisted_this));
346                         }
347
348                         //
349                         // Setting currect anonymous method to null blocks any further variable hoisting
350                         //
351                         AnonymousExpression ae = ec.CurrentAnonymousMethod;
352                         ec.CurrentAnonymousMethod = null;
353
354                         if (hoisted_params != null) {
355                                 EmitHoistedParameters (ec, hoisted_params);
356                         }
357
358                         ec.CurrentAnonymousMethod = ae;
359                 }
360
361                 protected virtual void EmitHoistedParameters (EmitContext ec, IList<HoistedParameter> hoisted)
362                 {
363                         foreach (HoistedParameter hp in hoisted) {
364                                 hp.EmitHoistingAssignment (ec);
365                         }
366                 }
367
368                 public override void EmitType ()
369                 {
370                         SymbolWriter.DefineAnonymousScope (ID);
371
372                         if (hoisted_this != null)
373                                 hoisted_this.EmitSymbolInfo ();
374
375                         if (hoisted_locals != null) {
376                                 foreach (HoistedVariable local in hoisted_locals)
377                                         local.EmitSymbolInfo ();
378                         }
379
380                         if (hoisted_params != null) {
381                                 foreach (HoistedParameter param in hoisted_params)
382                                         param.EmitSymbolInfo ();
383                         }
384
385                         if (used_parent_storeys != null) {
386                                 foreach (StoreyFieldPair sf in used_parent_storeys) {
387                                         SymbolWriter.DefineCapturedScope (ID, sf.Storey.ID, sf.Field.Name);
388                                 }
389                         }
390
391                         base.EmitType ();
392                 }
393
394                 public AnonymousMethodStorey GetGenericStorey ()
395                 {
396                         DeclSpace storey = this;
397                         while (storey != null && storey.CurrentTypeParameters == null)
398                                 storey = storey.Parent;
399
400                         return storey as AnonymousMethodStorey;
401                 }
402
403                 //
404                 // Returns a field which holds referenced storey instance
405                 //
406                 Field GetReferencedStoreyField (AnonymousMethodStorey storey)
407                 {
408                         if (used_parent_storeys == null)
409                                 return null;
410
411                         foreach (StoreyFieldPair sf in used_parent_storeys) {
412                                 if (sf.Storey == storey)
413                                         return sf.Field;
414                         }
415
416                         return null;
417                 }
418
419                 //
420                 // Creates storey instance expression regardless of currect IP
421                 //
422                 public Expression GetStoreyInstanceExpression (EmitContext ec)
423                 {
424                         AnonymousExpression am = ec.CurrentAnonymousMethod;
425
426                         //
427                         // Access from original block -> storey
428                         //
429                         if (am == null)
430                                 return Instance;
431
432                         //
433                         // Access from anonymous method implemented as a static -> storey
434                         //
435                         if (am.Storey == null)
436                                 return Instance;
437
438                         Field f = am.Storey.GetReferencedStoreyField (this);
439                         if (f == null) {
440                                 if (am.Storey == this) {
441                                         //
442                                         // Access inside of same storey (S -> S)
443                                         //
444                                         return new CompilerGeneratedThis (TypeBuilder, Location);
445                                 }
446                                 //
447                                 // External field access
448                                 //
449                                 return Instance;
450                         }
451
452                         //
453                         // Storey was cached to local field
454                         //
455                         FieldExpr f_ind = new FieldExpr (f, Location);
456                         f_ind.InstanceExpression = new CompilerGeneratedThis (TypeBuilder, Location);
457                         return f_ind;
458                 }
459
460                 protected virtual string GetVariableMangledName (LocalInfo local_info)
461                 {
462                         //
463                         // No need to mangle anonymous method hoisted variables cause they
464                         // are hoisted in their own scopes
465                         //
466                         return local_info.Name;
467                 }
468
469                 public HoistedThis HoistedThis {
470                         get { return hoisted_this; }
471                 }
472
473                 //
474                 // Mutate type dispatcher
475                 //
476                 public Type MutateType (Type type)
477                 {
478                         if (TypeManager.IsGenericType (type))
479                                 return MutateGenericType (type);
480
481                         if (TypeManager.IsGenericParameter (type))
482                                 return MutateGenericArgument (type);
483
484                         if (type.IsArray)
485                                 return MutateArrayType (type);
486                         return type;
487                 }
488
489                 //
490                 // Changes method type arguments (MVAR) to storey (VAR) type arguments
491                 //
492                 public void MutateGenericMethod (MethodSpec ms)
493                 {
494                         var method = (MethodInfo) ms.MetaInfo;
495                         Type [] t_args = TypeManager.GetGenericArguments (method);
496                         if (TypeManager.IsGenericType (method.DeclaringType)) {
497                                 Type t = MutateGenericType (method.DeclaringType);
498                                 if (t != method.DeclaringType) {
499                                         method = (MethodInfo) TypeManager.DropGenericMethodArguments (method);
500                                         if (TypeManager.IsBeingCompiled (method))
501                                                 ms.MetaInfo = TypeBuilder.GetMethod (t, method);
502                                         else
503                                                 ms.MetaInfo = MethodInfo.GetMethodFromHandle (method.MethodHandle, t.TypeHandle);
504                                 }                               
505                         }
506
507                         if (t_args == null || t_args.Length == 0)
508                                 return;
509
510                         for (int i = 0; i < t_args.Length; ++i)
511                                 t_args [i] = MutateType (t_args [i]);
512
513                         method = (MethodInfo) ms.MetaInfo;
514                         ms.MetaInfo = method.GetGenericMethodDefinition ().MakeGenericMethod (t_args);
515                 }
516
517                 public void MutateConstructor (MethodSpec ms)
518                 {
519                         var ctor = (ConstructorInfo) ms.MetaInfo;
520                         if (TypeManager.IsGenericType (ctor.DeclaringType)) {
521                                 Type t = MutateGenericType (ctor.DeclaringType);
522                                 if (t != ctor.DeclaringType) {
523                                         ctor = (ConstructorInfo) TypeManager.DropGenericMethodArguments (ctor);
524                                         if (TypeManager.IsBeingCompiled (ctor))
525                                                 ms.MetaInfo = TypeBuilder.GetConstructor (t, ctor);
526                                         else
527                                                 ms.MetaInfo = ConstructorInfo.GetMethodFromHandle (ctor.MethodHandle, t.TypeHandle);
528                                 }
529                         }
530                 }
531                 
532                 public void MutateField (FieldSpec fs)
533                 {
534                         var field = fs.MetaInfo;
535                         if (TypeManager.IsGenericType (field.DeclaringType)) {
536                                 Type t = MutateGenericType (field.DeclaringType);
537                                 if (t != field.DeclaringType) {
538                                         field = TypeManager.DropGenericTypeArguments (field.DeclaringType).GetField (field.Name, TypeManager.AllMembers);
539                                         
540                                         // HACK: TypeBuilder has to be used when a type is of TypeBuilder* but there is no
541                                         // way how to find out (use type comparison when this becomes an issue)
542                                         if (t.GetType ().FullName == "System.Reflection.MonoGenericClass") {
543                                                 fs.MetaInfo = TypeBuilder.GetField (t, field);
544                                         } else {
545                                                 fs.MetaInfo = FieldInfo.GetFieldFromHandle (field.FieldHandle, t.TypeHandle);
546                                         }
547                                 }
548                         }
549                 }               
550
551                 protected Type MutateArrayType (Type array)
552                 {
553                         Type element = TypeManager.GetElementType (array);
554                         if (element.IsArray) {
555                                 element = MutateArrayType (element);
556                         } else if (TypeManager.IsGenericParameter (element)) {
557                                 element = MutateGenericArgument (element);
558                         } else if (TypeManager.IsGenericType (element)) {
559                                 element = MutateGenericType (element);
560                         } else {
561                                 return array;
562                         }
563
564                         int rank = array.GetArrayRank ();
565                         if (rank == 1)
566                                 return element.MakeArrayType ();
567
568                         return element.MakeArrayType (rank);
569                 }
570
571                 protected Type MutateGenericType (Type type)
572                 {
573                         Type [] t_args = TypeManager.GetTypeArguments (type);
574                         if (t_args == null || t_args.Length == 0)
575                                 return type;
576
577                         for (int i = 0; i < t_args.Length; ++i)
578                                 t_args [i] = MutateType (t_args [i]);
579
580                         return TypeManager.DropGenericTypeArguments (type).MakeGenericType (t_args);
581                 }
582
583                 //
584                 // Changes method generic argument (MVAR) to type generic argument (VAR)
585                 //
586                 public Type MutateGenericArgument (Type type)
587                 {
588                         if (CurrentTypeParameters != null) {
589                                 TypeParameter tp = TypeParameter.FindTypeParameter (CurrentTypeParameters, type.Name);
590                                 if (tp != null)
591                                         return tp.Type;
592                         }
593
594                         return type;
595                 }
596
597                 public IList<ExplicitBlock> ReferencesFromChildrenBlock {
598                         get { return children_references; }
599                 }
600
601                 public static void Reset ()
602                 {
603                         unique_id = 0;
604                 }               
605         }
606
607         public abstract class HoistedVariable
608         {
609                 //
610                 // Hoisted version of variable references used in expression
611                 // tree has to be delayed until we know its location. The variable
612                 // doesn't know its location until all stories are calculated
613                 //
614                 class ExpressionTreeVariableReference : Expression
615                 {
616                         readonly HoistedVariable hv;
617
618                         public ExpressionTreeVariableReference (HoistedVariable hv)
619                         {
620                                 this.hv = hv;
621                         }
622
623                         public override Expression CreateExpressionTree (ResolveContext ec)
624                         {
625                                 throw new NotSupportedException ("ET");
626                         }
627
628                         protected override Expression DoResolve (ResolveContext ec)
629                         {
630                                 eclass = ExprClass.Value;
631                                 type = TypeManager.expression_type_expr.Type;
632                                 return this;
633                         }
634
635                         public override void Emit (EmitContext ec)
636                         {
637                                 ResolveContext rc = new ResolveContext (ec.MemberContext);
638                                 Expression e = hv.GetFieldExpression (ec).CreateExpressionTree (rc);
639                                 // This should never fail
640                                 e = e.Resolve (rc);
641                                 if (e != null)
642                                         e.Emit (ec);
643                         }
644                 }
645         
646                 protected readonly AnonymousMethodStorey storey;
647                 protected Field field;
648                 Dictionary<AnonymousExpression, FieldExpr> cached_inner_access; // TODO: Hashtable is too heavyweight
649                 FieldExpr cached_outer_access;
650
651                 protected HoistedVariable (AnonymousMethodStorey storey, string name, Type type)
652                         : this (storey, storey.AddCapturedVariable (name, type))
653                 {
654                 }
655
656                 protected HoistedVariable (AnonymousMethodStorey storey, Field field)
657                 {
658                         this.storey = storey;
659                         this.field = field;
660                 }
661
662                 public void AddressOf (EmitContext ec, AddressOp mode)
663                 {
664                         GetFieldExpression (ec).AddressOf (ec, mode);
665                 }
666
667                 public Expression CreateExpressionTree ()
668                 {
669                         return new ExpressionTreeVariableReference (this);
670                 }
671
672                 public void Emit (EmitContext ec)
673                 {
674                         GetFieldExpression (ec).Emit (ec);
675                 }
676
677                 //
678                 // Creates field access expression for hoisted variable
679                 //
680                 protected FieldExpr GetFieldExpression (EmitContext ec)
681                 {
682                         if (ec.CurrentAnonymousMethod == null || ec.CurrentAnonymousMethod.Storey == null) {
683                                 if (cached_outer_access != null)
684                                         return cached_outer_access;
685
686                                 //
687                                 // When setting top-level hoisted variable in generic storey
688                                 // change storey generic types to method generic types (VAR -> MVAR)
689                                 //
690                                 cached_outer_access = storey.MemberName.IsGeneric ?
691                                         new FieldExpr (field, storey.Instance.Type, field.Location) :
692                                         new FieldExpr (field, field.Location);
693
694                                 cached_outer_access.InstanceExpression = storey.GetStoreyInstanceExpression (ec);
695                                 return cached_outer_access;
696                         }
697
698                         FieldExpr inner_access;
699                         if (cached_inner_access != null) {
700                                 if (!cached_inner_access.TryGetValue (ec.CurrentAnonymousMethod, out inner_access))
701                                         inner_access = null;
702                         } else {
703                                 inner_access = null;
704                                 cached_inner_access = new Dictionary<AnonymousExpression, FieldExpr> (4);
705                         }
706
707                         if (inner_access == null) {
708                                 inner_access = field.Parent.MemberName.IsGeneric ?
709                                         new FieldExpr (field, field.Parent.CurrentType, field.Location) :
710                                         new FieldExpr (field, field.Location);
711                                                         
712                                 inner_access.InstanceExpression = storey.GetStoreyInstanceExpression (ec);
713                                 cached_inner_access.Add (ec.CurrentAnonymousMethod, inner_access);
714                         }
715
716                         return inner_access;
717                 }
718
719                 public abstract void EmitSymbolInfo ();
720
721                 public void Emit (EmitContext ec, bool leave_copy)
722                 {
723                         GetFieldExpression (ec).Emit (ec, leave_copy);
724                 }
725
726                 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
727                 {
728                         GetFieldExpression (ec).EmitAssign (ec, source, leave_copy, false);
729                 }
730         }
731
732         public class HoistedParameter : HoistedVariable
733         {
734                 sealed class HoistedFieldAssign : Assign
735                 {
736                         public HoistedFieldAssign (Expression target, Expression source)
737                                 : base (target, source, source.Location)
738                         {
739                         }
740
741                         protected override Expression ResolveConversions (ResolveContext ec)
742                         {
743                                 //
744                                 // Implicit conversion check fails for hoisted type arguments
745                                 // as they are of different types (!!0 x !0)
746                                 //
747                                 return this;
748                         }
749                 }
750
751                 readonly ParameterReference parameter;
752
753                 public HoistedParameter (AnonymousMethodStorey scope, ParameterReference par)
754                         : base (scope, par.Name, par.Type)
755                 {
756                         this.parameter = par;
757                 }
758
759                 public HoistedParameter (HoistedParameter hp, string name)
760                         : base (hp.storey, name, hp.parameter.Type)
761                 {
762                         this.parameter = hp.parameter;
763                 }
764
765                 public void EmitHoistingAssignment (EmitContext ec)
766                 {
767                         //
768                         // Remove hoisted redirection to emit assignment from original parameter
769                         //
770                         HoistedVariable temp = parameter.Parameter.HoistedVariant;
771                         parameter.Parameter.HoistedVariant = null;
772
773                         Assign a = new HoistedFieldAssign (GetFieldExpression (ec), parameter);
774                         if (a.Resolve (new ResolveContext (ec.MemberContext)) != null)
775                                 a.EmitStatement (ec);
776
777                         parameter.Parameter.HoistedVariant = temp;
778                 }
779
780                 public override void EmitSymbolInfo ()
781                 {
782                         SymbolWriter.DefineCapturedParameter (storey.ID, field.Name, field.Name);
783                 }
784
785                 public Field Field {
786                         get { return field; }
787                 }
788         }
789
790         class HoistedLocalVariable : HoistedVariable
791         {
792                 readonly string name;
793
794                 public HoistedLocalVariable (AnonymousMethodStorey scope, LocalInfo local, string name)
795                         : base (scope, name, local.VariableType)
796                 {
797                         this.name = local.Name;
798                 }
799
800                 public override void EmitSymbolInfo ()
801                 {
802                         SymbolWriter.DefineCapturedLocal (storey.ID, name, field.Name);
803                 }
804         }
805
806         public class HoistedThis : HoistedVariable
807         {
808                 public HoistedThis (AnonymousMethodStorey storey, Field field)
809                         : base (storey, field)
810                 {
811                 }
812
813                 public void EmitHoistingAssignment (EmitContext ec)
814                 {
815                         SimpleAssign a = new SimpleAssign (GetFieldExpression (ec), new CompilerGeneratedThis (ec.CurrentType, field.Location));
816                         if (a.Resolve (new ResolveContext (ec.MemberContext)) != null)
817                                 a.EmitStatement (ec);
818                 }
819
820                 public override void EmitSymbolInfo ()
821                 {
822                         SymbolWriter.DefineCapturedThis (storey.ID, field.Name);
823                 }
824
825                 public Field Field {
826                         get { return field; }
827                 }
828         }
829
830         //
831         // Anonymous method expression as created by parser
832         //
833         public class AnonymousMethodExpression : Expression
834         {
835                 //
836                 // Special conversion for nested expression tree lambdas
837                 //
838                 class Quote : ShimExpression
839                 {
840                         public Quote (Expression expr)
841                                 : base (expr)
842                         {
843                         }
844
845                         public override Expression CreateExpressionTree (ResolveContext ec)
846                         {
847                                 var args = new Arguments (1);
848                                 args.Add (new Argument (expr.CreateExpressionTree (ec)));
849                                 return CreateExpressionFactoryCall (ec, "Quote", args);
850                         }
851
852                         protected override Expression DoResolve (ResolveContext rc)
853                         {
854                                 expr = expr.Resolve (rc);
855                                 if (expr == null)
856                                         return null;
857
858                                 eclass = expr.eclass;
859                                 type = expr.Type;
860                                 return this;
861                         }
862                 }
863
864                 Dictionary<Type, Expression> compatibles;
865                 public ToplevelBlock Block;
866
867                 public AnonymousMethodExpression (Location loc)
868                 {
869                         this.loc = loc;
870                         this.compatibles = new Dictionary<Type, Expression> ();
871                 }
872
873                 public override string ExprClassName {
874                         get {
875                                 return "anonymous method";
876                         }
877                 }
878
879                 public virtual bool HasExplicitParameters {
880                         get {
881                                 return Parameters != ParametersCompiled.Undefined;
882                         }
883                 }
884                 
885                 public ParametersCompiled Parameters {
886                         get { return Block.Parameters; }
887                 }
888
889                 //
890                 // Returns true if the body of lambda expression can be implicitly
891                 // converted to the delegate of type `delegate_type'
892                 //
893                 public bool ImplicitStandardConversionExists (ResolveContext ec, Type delegate_type)
894                 {
895                         using (ec.With (ResolveContext.Options.InferReturnType, false)) {
896                                 using (ec.Set (ResolveContext.Options.ProbingMode)) {
897                                         return Compatible (ec, delegate_type) != null;
898                                 }
899                         }
900                 }
901
902                 protected Type CompatibleChecks (ResolveContext ec, Type delegate_type)
903                 {
904                         if (TypeManager.IsDelegateType (delegate_type))
905                                 return delegate_type;
906
907                         if (TypeManager.DropGenericTypeArguments (delegate_type) == TypeManager.expression_type) {
908                                 delegate_type = TypeManager.GetTypeArguments (delegate_type) [0];
909                                 if (TypeManager.IsDelegateType (delegate_type))
910                                         return delegate_type;
911
912                                 ec.Report.Error (835, loc, "Cannot convert `{0}' to an expression tree of non-delegate type `{1}'",
913                                         GetSignatureForError (), TypeManager.CSharpName (delegate_type));
914                                 return null;
915                         }
916
917                         ec.Report.Error (1660, loc, "Cannot convert `{0}' to non-delegate type `{1}'",
918                                       GetSignatureForError (), TypeManager.CSharpName (delegate_type));
919                         return null;
920                 }
921
922                 protected bool VerifyExplicitParameters (ResolveContext ec, Type delegate_type, AParametersCollection parameters)
923                 {
924                         if (VerifyParameterCompatibility (ec, delegate_type, parameters, ec.IsInProbingMode))
925                                 return true;
926
927                         if (!ec.IsInProbingMode)
928                                 ec.Report.Error (1661, loc,
929                                         "Cannot convert `{0}' to delegate type `{1}' since there is a parameter mismatch",
930                                         GetSignatureForError (), TypeManager.CSharpName (delegate_type));
931
932                         return false;
933                 }
934
935                 protected bool VerifyParameterCompatibility (ResolveContext ec, Type delegate_type, AParametersCollection invoke_pd, bool ignore_errors)
936                 {
937                         if (Parameters.Count != invoke_pd.Count) {
938                                 if (ignore_errors)
939                                         return false;
940                                 
941                                 ec.Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments",
942                                               TypeManager.CSharpName (delegate_type), Parameters.Count.ToString ());
943                                 return false;
944                         }
945
946                         bool has_implicit_parameters = !HasExplicitParameters;
947                         bool error = false;
948
949                         for (int i = 0; i < Parameters.Count; ++i) {
950                                 Parameter.Modifier p_mod = invoke_pd.FixedParameters [i].ModFlags;
951                                 if (Parameters.FixedParameters [i].ModFlags != p_mod && p_mod != Parameter.Modifier.PARAMS) {
952                                         if (ignore_errors)
953                                                 return false;
954                                         
955                                         if (p_mod == Parameter.Modifier.NONE)
956                                                 ec.Report.Error (1677, loc, "Parameter `{0}' should not be declared with the `{1}' keyword",
957                                                               (i + 1).ToString (), Parameter.GetModifierSignature (Parameters.FixedParameters [i].ModFlags));
958                                         else
959                                                 ec.Report.Error (1676, loc, "Parameter `{0}' must be declared with the `{1}' keyword",
960                                                               (i+1).ToString (), Parameter.GetModifierSignature (p_mod));
961                                         error = true;
962                                 }
963
964                                 if (has_implicit_parameters)
965                                         continue;
966
967                                 Type type = invoke_pd.Types [i];
968                                 
969                                 // We assume that generic parameters are always inflated
970                                 if (TypeManager.IsGenericParameter (type))
971                                         continue;
972                                 
973                                 if (TypeManager.HasElementType (type) && TypeManager.IsGenericParameter (TypeManager.GetElementType (type)))
974                                         continue;
975                                 
976                                 if (invoke_pd.Types [i] != Parameters.Types [i]) {
977                                         if (ignore_errors)
978                                                 return false;
979                                         
980                                         ec.Report.Error (1678, loc, "Parameter `{0}' is declared as type `{1}' but should be `{2}'",
981                                                       (i+1).ToString (),
982                                                       TypeManager.CSharpName (Parameters.Types [i]),
983                                                       TypeManager.CSharpName (invoke_pd.Types [i]));
984                                         error = true;
985                                 }
986                         }
987
988                         return !error;
989                 }
990
991                 //
992                 // Infers type arguments based on explicit arguments
993                 //
994                 public bool ExplicitTypeInference (ResolveContext ec, TypeInferenceContext type_inference, Type delegate_type)
995                 {
996                         if (!HasExplicitParameters)
997                                 return false;
998
999                         if (!TypeManager.IsDelegateType (delegate_type)) {
1000                                 if (TypeManager.DropGenericTypeArguments (delegate_type) != TypeManager.expression_type)
1001                                         return false;
1002
1003                                 delegate_type = TypeManager.GetTypeArguments (delegate_type) [0];
1004                                 if (!TypeManager.IsDelegateType (delegate_type))
1005                                         return false;
1006                         }
1007                         
1008                         AParametersCollection d_params = TypeManager.GetDelegateParameters (ec, delegate_type);
1009                         if (d_params.Count != Parameters.Count)
1010                                 return false;
1011
1012                         for (int i = 0; i < Parameters.Count; ++i) {
1013                                 Type itype = d_params.Types [i];
1014                                 if (!TypeManager.IsGenericParameter (itype)) {
1015                                         if (!TypeManager.HasElementType (itype))
1016                                                 continue;
1017                                         
1018                                         if (!TypeManager.IsGenericParameter (TypeManager.GetElementType (itype)))
1019                                             continue;
1020                                 }
1021                                 type_inference.ExactInference (Parameters.Types [i], itype);
1022                         }
1023                         return true;
1024                 }
1025
1026                 public Type InferReturnType (ResolveContext ec, TypeInferenceContext tic, Type delegate_type)
1027                 {
1028                         AnonymousExpression am;
1029                         using (ec.Set (ResolveContext.Options.ProbingMode | ResolveContext.Options.InferReturnType)) {
1030                                 am = CompatibleMethodBody (ec, tic, InternalType.Arglist, delegate_type);
1031                                 if (am != null)
1032                                         am = am.Compatible (ec);
1033                         }
1034                         
1035                         if (am == null)
1036                                 return null;
1037
1038                         return am.ReturnType;
1039                 }
1040
1041                 //
1042                 // Returns AnonymousMethod container if this anonymous method
1043                 // expression can be implicitly converted to the delegate type `delegate_type'
1044                 //
1045                 public Expression Compatible (ResolveContext ec, Type type)
1046                 {
1047                         Expression am;
1048                         if (compatibles.TryGetValue (type, out am))
1049                                 return am;
1050
1051                         Type delegate_type = CompatibleChecks (ec, type);
1052                         if (delegate_type == null)
1053                                 return null;
1054
1055                         //
1056                         // At this point its the first time we know the return type that is 
1057                         // needed for the anonymous method.  We create the method here.
1058                         //
1059
1060                         var invoke_mb = Delegate.GetInvokeMethod (ec.Compiler,
1061                                 ec.CurrentType, delegate_type);
1062                         Type return_type = TypeManager.TypeToCoreType (invoke_mb.ReturnType);
1063
1064 #if MS_COMPATIBLE
1065                         Type[] g_args = delegate_type.GetGenericArguments ();
1066                         if (return_type.IsGenericParameter)
1067                                 return_type = g_args [return_type.GenericParameterPosition];
1068 #endif
1069
1070                         //
1071                         // Second: the return type of the delegate must be compatible with 
1072                         // the anonymous type.   Instead of doing a pass to examine the block
1073                         // we satisfy the rule by setting the return type on the EmitContext
1074                         // to be the delegate type return type.
1075                         //
1076
1077                         var body = CompatibleMethodBody (ec, null, return_type, delegate_type);
1078                         if (body == null)
1079                                 return null;
1080
1081                         bool etree_conversion = delegate_type != type;
1082
1083                         try {
1084                                 if (etree_conversion) {
1085                                         if (ec.HasSet (ResolveContext.Options.ExpressionTreeConversion)) {
1086                                                 //
1087                                                 // Nested expression tree lambda use same scope as parent
1088                                                 // lambda, this also means no variable capturing between this
1089                                                 // and parent scope
1090                                                 //
1091                                                 am = body.Compatible (ec, ec.CurrentAnonymousMethod);
1092
1093                                                 //
1094                                                 // Quote nested expression tree
1095                                                 //
1096                                                 if (am != null)
1097                                                         am = new Quote (am);
1098                                         } else {
1099                                                 int errors = ec.Report.Errors;
1100
1101                                                 using (ec.Set (ResolveContext.Options.ExpressionTreeConversion)) {
1102                                                         am = body.Compatible (ec);
1103                                                 }
1104
1105                                                 //
1106                                                 // Rewrite expressions into expression tree when targeting Expression<T>
1107                                                 //
1108                                                 if (am != null && errors == ec.Report.Errors)
1109                                                         am = CreateExpressionTree (ec, delegate_type);
1110                                         }
1111                                 } else {
1112                                         am = body.Compatible (ec);
1113                                 }
1114                         } catch (CompletionResult) {
1115                                 throw;
1116                         } catch (Exception e) {
1117                                 throw new InternalErrorException (e, loc);
1118                         }
1119                         
1120                         if (!ec.IsInProbingMode)
1121                                 compatibles.Add (type, am == null ? EmptyExpression.Null : am);
1122
1123                         return am;
1124                 }
1125
1126                 protected virtual Expression CreateExpressionTree (ResolveContext ec, Type delegate_type)
1127                 {
1128                         return CreateExpressionTree (ec);
1129                 }
1130
1131                 public override Expression CreateExpressionTree (ResolveContext ec)
1132                 {
1133                         ec.Report.Error (1946, loc, "An anonymous method cannot be converted to an expression tree");
1134                         return null;
1135                 }
1136
1137                 protected virtual ParametersCompiled ResolveParameters (ResolveContext ec, TypeInferenceContext tic, Type delegate_type)
1138                 {
1139                         AParametersCollection delegate_parameters = TypeManager.GetDelegateParameters (ec, delegate_type);
1140
1141                         if (Parameters == ParametersCompiled.Undefined) {
1142                                 //
1143                                 // We provide a set of inaccessible parameters
1144                                 //
1145                                 Parameter[] fixedpars = new Parameter[delegate_parameters.Count];
1146
1147                                 for (int i = 0; i < delegate_parameters.Count; i++) {
1148                                         Parameter.Modifier i_mod = delegate_parameters.FixedParameters [i].ModFlags;
1149                                         if (i_mod == Parameter.Modifier.OUT) {
1150                                                 ec.Report.Error (1688, loc, "Cannot convert anonymous " +
1151                                                                   "method block without a parameter list " +
1152                                                                   "to delegate type `{0}' because it has " +
1153                                                                   "one or more `out' parameters.",
1154                                                                   TypeManager.CSharpName (delegate_type));
1155                                                 return null;
1156                                         }
1157                                         fixedpars[i] = new Parameter (
1158                                                 null, null,
1159                                                 delegate_parameters.FixedParameters [i].ModFlags, null, loc);
1160                                 }
1161
1162                                 return ParametersCompiled.CreateFullyResolved (fixedpars, delegate_parameters.Types);
1163                         }
1164
1165                         if (!VerifyExplicitParameters (ec, delegate_type, delegate_parameters)) {
1166                                 return null;
1167                         }
1168
1169                         return Parameters;
1170                 }
1171
1172                 protected override Expression DoResolve (ResolveContext ec)
1173                 {
1174                         if (ec.HasSet (ResolveContext.Options.ConstantScope)) {
1175                                 ec.Report.Error (1706, loc, "Anonymous methods and lambda expressions cannot be used in the current context");
1176                                 return null;
1177                         }
1178
1179                         //
1180                         // Set class type, set type
1181                         //
1182
1183                         eclass = ExprClass.Value;
1184
1185                         //
1186                         // This hack means `The type is not accessible
1187                         // anywhere', we depend on special conversion
1188                         // rules.
1189                         // 
1190                         type = InternalType.AnonymousMethod;
1191
1192                         if ((Parameters != null) && !Parameters.Resolve (ec))
1193                                 return null;
1194
1195                         // FIXME: The emitted code isn't very careful about reachability
1196                         // so, ensure we have a 'ret' at the end
1197                         BlockContext bc = ec as BlockContext;
1198                         if (bc != null && bc.CurrentBranching != null && bc.CurrentBranching.CurrentUsageVector.IsUnreachable)
1199                                 bc.NeedReturnLabel ();
1200
1201                         return this;
1202                 }
1203
1204                 public override void Emit (EmitContext ec)
1205                 {
1206                         // nothing, as we only exist to not do anything.
1207                 }
1208
1209                 public static void Error_AddressOfCapturedVar (ResolveContext ec, IVariableReference var, Location loc)
1210                 {
1211                         ec.Report.Error (1686, loc,
1212                                 "Local variable or parameter `{0}' cannot have their address taken and be used inside an anonymous method or lambda expression",
1213                                 var.Name);
1214                 }
1215
1216                 public override string GetSignatureForError ()
1217                 {
1218                         return ExprClassName;
1219                 }
1220
1221                 AnonymousMethodBody CompatibleMethodBody (ResolveContext ec, TypeInferenceContext tic, Type return_type, Type delegate_type)
1222                 {
1223                         ParametersCompiled p = ResolveParameters (ec, tic, delegate_type);
1224                         if (p == null)
1225                                 return null;
1226
1227                         ToplevelBlock b = ec.IsInProbingMode ? (ToplevelBlock) Block.PerformClone () : Block;
1228
1229                         return CompatibleMethodFactory (return_type, delegate_type, p, b);
1230
1231                 }
1232
1233                 protected virtual AnonymousMethodBody CompatibleMethodFactory (Type return_type, Type delegate_type, ParametersCompiled p, ToplevelBlock b)
1234                 {
1235                         return new AnonymousMethodBody (p, b, return_type, delegate_type, loc);
1236                 }
1237
1238                 protected override void CloneTo (CloneContext clonectx, Expression t)
1239                 {
1240                         AnonymousMethodExpression target = (AnonymousMethodExpression) t;
1241
1242                         target.Block = (ToplevelBlock) clonectx.LookupBlock (Block);
1243                 }
1244         }
1245
1246         //
1247         // Abstract expression for any block which requires variables hoisting
1248         //
1249         public abstract class AnonymousExpression : Expression
1250         {
1251                 protected class AnonymousMethodMethod : Method
1252                 {
1253                         public readonly AnonymousExpression AnonymousMethod;
1254                         public readonly AnonymousMethodStorey Storey;
1255                         readonly string RealName;
1256
1257                         public AnonymousMethodMethod (DeclSpace parent, AnonymousExpression am, AnonymousMethodStorey storey,
1258                                                           GenericMethod generic, TypeExpr return_type,
1259                                                           Modifiers mod, string real_name, MemberName name,
1260                                                           ParametersCompiled parameters)
1261                                 : base (parent, generic, return_type, mod | Modifiers.COMPILER_GENERATED,
1262                                                 name, parameters, null)
1263                         {
1264                                 this.AnonymousMethod = am;
1265                                 this.Storey = storey;
1266                                 this.RealName = real_name;
1267
1268                                 Parent.PartialContainer.AddMethod (this);
1269                                 Block = am.Block;
1270                         }
1271
1272                         public override EmitContext CreateEmitContext (ILGenerator ig)
1273                         {
1274                                 EmitContext ec = new EmitContext (this, ig, ReturnType);
1275                                 ec.CurrentAnonymousMethod = AnonymousMethod;
1276                                 if (AnonymousMethod.return_label != null) {
1277                                         ec.HasReturnLabel = true;
1278                                         ec.ReturnLabel = (Label) AnonymousMethod.return_label;
1279                                 }
1280
1281                                 return ec;
1282                         }
1283
1284                         protected override bool ResolveMemberType ()
1285                         {
1286                                 if (!base.ResolveMemberType ())
1287                                         return false;
1288
1289                                 if (Storey != null && Storey.IsGeneric) {
1290                                         AnonymousMethodStorey gstorey = Storey.GetGenericStorey ();
1291                                         if (gstorey != null) {
1292                                                 if (!Parameters.IsEmpty) {
1293                                                         Type [] ptypes = Parameters.Types;
1294                                                         for (int i = 0; i < ptypes.Length; ++i)
1295                                                                 ptypes [i] = gstorey.MutateType (ptypes [i]);
1296                                                 }
1297
1298                                                 member_type = gstorey.MutateType (member_type);
1299                                         }
1300                                 }
1301
1302                                 return true;
1303                         }
1304
1305                         public override void Emit ()
1306                         {
1307                                 //
1308                                 // Before emitting any code we have to change all MVAR references to VAR
1309                                 // when the method is of generic type and has hoisted variables
1310                                 //
1311                                 if (Storey == Parent && Storey.IsGeneric) {
1312                                         AnonymousMethodStorey gstorey = Storey.GetGenericStorey ();
1313                                         if (gstorey != null) {
1314                                                 block.MutateHoistedGenericType (gstorey);
1315                                         }
1316                                 }
1317
1318                                 if (MethodBuilder == null) {
1319                                         Define ();
1320                                 }
1321
1322                                 base.Emit ();
1323                         }
1324
1325                         public override void EmitExtraSymbolInfo (SourceMethod source)
1326                         {
1327                                 source.SetRealMethodName (RealName);
1328                         }
1329                 }
1330
1331                 readonly ToplevelBlock block;
1332
1333                 public Type ReturnType;
1334
1335                 object return_label;
1336
1337                 protected AnonymousExpression (ToplevelBlock block, Type return_type, Location loc)
1338                 {
1339                         this.ReturnType = return_type;
1340                         this.block = block;
1341                         this.loc = loc;
1342                 }
1343
1344                 public abstract string ContainerType { get; }
1345                 public abstract bool IsIterator { get; }
1346                 public abstract AnonymousMethodStorey Storey { get; }
1347
1348                 public AnonymousExpression Compatible (ResolveContext ec)
1349                 {
1350                         return Compatible (ec, this);
1351                 }
1352
1353                 public AnonymousExpression Compatible (ResolveContext ec, AnonymousExpression ae)
1354                 {
1355                         // TODO: Implement clone
1356                         BlockContext aec = new BlockContext (ec.MemberContext, Block, ReturnType);
1357                         aec.CurrentAnonymousMethod = ae;
1358
1359                         IDisposable aec_dispose = null;
1360                         ResolveContext.Options flags = 0;
1361                         if (ec.HasSet (ResolveContext.Options.InferReturnType)) {
1362                                 flags |= ResolveContext.Options.InferReturnType;
1363                                 aec.ReturnTypeInference = new TypeInferenceContext ();
1364                         }
1365
1366                         if (ec.IsInProbingMode)
1367                                 flags |= ResolveContext.Options.ProbingMode;
1368
1369                         if (ec.HasSet (ResolveContext.Options.FieldInitializerScope))
1370                                 flags |= ResolveContext.Options.FieldInitializerScope;
1371
1372                         if (ec.IsUnsafe)
1373                                 flags |= ResolveContext.Options.UnsafeScope;
1374
1375                         if (ec.HasSet (ResolveContext.Options.CheckedScope))
1376                                 flags |= ResolveContext.Options.CheckedScope;
1377
1378                         if (ec.HasSet (ResolveContext.Options.ExpressionTreeConversion))
1379                                 flags |= ResolveContext.Options.ExpressionTreeConversion;
1380
1381                         // HACK: Flag with 0 cannot be set 
1382                         if (flags != 0)
1383                                 aec_dispose = aec.Set (flags);
1384
1385                         bool res = Block.Resolve (ec.CurrentBranching, aec, Block.Parameters, null);
1386
1387                         if (aec.HasReturnLabel)
1388                                 return_label = aec.ReturnLabel;
1389
1390                         if (ec.HasSet (ResolveContext.Options.InferReturnType)) {
1391                                 aec.ReturnTypeInference.FixAllTypes (ec);
1392                                 ReturnType = aec.ReturnTypeInference.InferredTypeArguments [0];
1393                         }
1394
1395                         if (aec_dispose != null) {
1396                                 aec_dispose.Dispose ();
1397                         }
1398
1399                         return res ? this : null;
1400                 }
1401
1402                 public void SetHasThisAccess ()
1403                 {
1404                         Block.HasCapturedThis = true;
1405                         ExplicitBlock b = Block.Parent.Explicit;
1406
1407                         while (b != null) {
1408                                 if (b.HasCapturedThis)
1409                                         return;
1410
1411                                 b.HasCapturedThis = true;
1412                                 b = b.Parent == null ? null : b.Parent.Explicit;
1413                         }
1414                 }
1415
1416                 //
1417                 // The block that makes up the body for the anonymous method
1418                 //
1419                 public ToplevelBlock Block {
1420                         get {
1421                                 return block;
1422                         }
1423                 }
1424
1425         }
1426
1427         public class AnonymousMethodBody : AnonymousExpression
1428         {
1429                 protected readonly ParametersCompiled parameters;
1430                 AnonymousMethodStorey storey;
1431
1432                 AnonymousMethodMethod method;
1433                 Field am_cache;
1434                 string block_name;
1435
1436                 static int unique_id;
1437
1438                 public AnonymousMethodBody (ParametersCompiled parameters,
1439                                         ToplevelBlock block, Type return_type, Type delegate_type,
1440                                         Location loc)
1441                         : base (block, return_type, loc)
1442                 {
1443                         this.type = delegate_type;
1444                         this.parameters = parameters;
1445                 }
1446
1447                 public override string ContainerType {
1448                         get { return "anonymous method"; }
1449                 }
1450
1451                 public override AnonymousMethodStorey Storey {
1452                         get { return storey; }
1453                 }
1454
1455                 public override bool IsIterator {
1456                         get { return false; }
1457                 }
1458
1459                 public override Expression CreateExpressionTree (ResolveContext ec)
1460                 {
1461                         ec.Report.Error (1945, loc, "An expression tree cannot contain an anonymous method expression");
1462                         return null;
1463                 }
1464
1465                 bool Define (ResolveContext ec)
1466                 {
1467                         if (!Block.Resolved && Compatible (ec) == null)
1468                                 return false;
1469
1470                         if (block_name == null) {
1471                                 MemberCore mc = (MemberCore) ec.MemberContext;
1472                                 block_name = mc.MemberName.Basename;
1473                         }
1474
1475                         return true;
1476                 }
1477
1478                 //
1479                 // Creates a host for the anonymous method
1480                 //
1481                 AnonymousMethodMethod DoCreateMethodHost (EmitContext ec)
1482                 {
1483                         //
1484                         // Anonymous method body can be converted to
1485                         //
1486                         // 1, an instance method in current scope when only `this' is hoisted
1487                         // 2, a static method in current scope when neither `this' nor any variable is hoisted
1488                         // 3, an instance method in compiler generated storey when any hoisted variable exists
1489                         //
1490
1491                         Modifiers modifiers;
1492                         if (Block.HasCapturedVariable || Block.HasCapturedThis) {
1493                                 storey = FindBestMethodStorey ();
1494                                 modifiers = storey != null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
1495                         } else {
1496                                 if (ec.CurrentAnonymousMethod != null)
1497                                         storey = ec.CurrentAnonymousMethod.Storey;
1498
1499                                 modifiers = Modifiers.STATIC | Modifiers.PRIVATE;
1500                         }
1501
1502                         TypeContainer parent = storey != null ? storey : ec.CurrentTypeDefinition;
1503
1504                         MemberCore mc = ec.MemberContext as MemberCore;
1505                         string name = CompilerGeneratedClass.MakeName (parent != storey ? block_name : null,
1506                                 "m", null, unique_id++);
1507
1508                         MemberName member_name;
1509                         GenericMethod generic_method;
1510                         if (storey == null && mc.MemberName.TypeArguments != null) {
1511                                 member_name = new MemberName (name, mc.MemberName.TypeArguments.Clone (), Location);
1512
1513                                 generic_method = new GenericMethod (parent.NamespaceEntry, parent, member_name,
1514                                         new TypeExpression (ReturnType, Location), parameters);
1515
1516                                 var list = new List<Constraints> ();
1517                                 foreach (TypeParameter tparam in ec.CurrentTypeParameters) {
1518                                         if (tparam.Constraints != null)
1519                                                 list.Add (tparam.Constraints.Clone ());
1520                                 }
1521                                 generic_method.SetParameterInfo (list);
1522                         } else {
1523                                 member_name = new MemberName (name, Location);
1524                                 generic_method = null;
1525                         }
1526
1527                         string real_name = String.Format (
1528                                 "{0}~{1}{2}", mc.GetSignatureForError (), GetSignatureForError (),
1529                                 parameters.GetSignatureForError ());
1530
1531                         return new AnonymousMethodMethod (parent,
1532                                 this, storey, generic_method, new TypeExpression (ReturnType, Location), modifiers,
1533                                 real_name, member_name, parameters);
1534                 }
1535
1536                 protected override Expression DoResolve (ResolveContext ec)
1537                 {
1538                         if (!Define (ec))
1539                                 return null;
1540
1541                         eclass = ExprClass.Value;
1542                         return this;
1543                 }
1544
1545                 public override void Emit (EmitContext ec)
1546                 {
1547                         //
1548                         // Use same anonymous method implementation for scenarios where same
1549                         // code is used from multiple blocks, e.g. field initializers
1550                         //
1551                         if (method == null) {
1552                                 //
1553                                 // Delay an anonymous method definition to avoid emitting unused code
1554                                 // for unreachable blocks or expression trees
1555                                 //
1556                                 method = DoCreateMethodHost (ec);
1557                                 method.Define ();
1558                         }
1559
1560                         bool is_static = (method.ModFlags & Modifiers.STATIC) != 0;
1561                         if (is_static && am_cache == null) {
1562                                 //
1563                                 // Creates a field cache to store delegate instance if it's not generic
1564                                 //
1565                                 if (!method.MemberName.IsGeneric) {
1566                                         TypeContainer parent = method.Parent.PartialContainer;
1567                                         int id = parent.Fields == null ? 0 : parent.Fields.Count;
1568                                         am_cache = new Field (parent, new TypeExpression (type, loc),
1569                                                 Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED,
1570                                                 new MemberName (CompilerGeneratedClass.MakeName (null, "f", "am$cache", id), loc), null);
1571                                         am_cache.Define ();
1572                                         parent.AddField (am_cache);
1573                                 } else {
1574                                         // TODO: Implement caching of generated generic static methods
1575                                         //
1576                                         // Idea:
1577                                         //
1578                                         // Some extra class is needed to capture variable generic type
1579                                         // arguments. Maybe we could re-use anonymous types, with a unique
1580                                         // anonymous method id, but they are quite heavy.
1581                                         //
1582                                         // Consider : "() => typeof(T);"
1583                                         //
1584                                         // We need something like
1585                                         // static class Wrap<Tn, Tm, DelegateType> {
1586                                         //              public static DelegateType cache;
1587                                         // }
1588                                         //
1589                                         // We then specialize local variable to capture all generic parameters
1590                                         // and delegate type, e.g. "Wrap<Ta, Tb, DelegateTypeInst> cache;"
1591                                         //
1592                                 }
1593                         }
1594
1595                         ILGenerator ig = ec.ig;
1596                         Label l_initialized = ig.DefineLabel ();
1597
1598                         if (am_cache != null) {
1599                                 ig.Emit (OpCodes.Ldsfld, am_cache.Spec.MetaInfo);
1600                                 ig.Emit (OpCodes.Brtrue_S, l_initialized);
1601                         }
1602
1603                         //
1604                         // Load method delegate implementation
1605                         //
1606
1607                         if (is_static) {
1608                                 ig.Emit (OpCodes.Ldnull);
1609                         } else if (storey != null) {
1610                                 Expression e = storey.GetStoreyInstanceExpression (ec).Resolve (new ResolveContext (ec.MemberContext));
1611                                 if (e != null)
1612                                         e.Emit (ec);
1613                         } else {
1614                                 ig.Emit (OpCodes.Ldarg_0);
1615                         }
1616
1617                         MethodInfo delegate_method = method.MethodBuilder;
1618                         if (storey != null && storey.MemberName.IsGeneric) {
1619                                 Type t = storey.Instance.Type;
1620                                 
1621                                 //
1622                                 // Mutate anonymous method instance type if we are in nested
1623                                 // hoisted generic anonymous method storey
1624                                 //
1625                                 if (ec.CurrentAnonymousMethod != null &&
1626                                         ec.CurrentAnonymousMethod.Storey != null &&
1627                                         ec.CurrentAnonymousMethod.Storey.IsGeneric) {
1628                                         t = storey.GetGenericStorey ().MutateType (t);
1629                                 }
1630
1631                                 delegate_method = TypeBuilder.GetMethod (t, delegate_method);
1632                         }
1633
1634                         ig.Emit (OpCodes.Ldftn, delegate_method);
1635
1636                         var constructor_method = Delegate.GetConstructor (ec.MemberContext.Compiler, ec.CurrentType, type);
1637 #if MS_COMPATIBLE
1638 //            if (type.IsGenericType && type is TypeBuilder)
1639 //                constructor_method = TypeBuilder.GetConstructor (type, constructor_method);
1640 #endif
1641                         ig.Emit (OpCodes.Newobj, (ConstructorInfo) constructor_method.MetaInfo);
1642
1643                         if (am_cache != null) {
1644                                 ig.Emit (OpCodes.Stsfld, am_cache.Spec.MetaInfo);
1645                                 ig.MarkLabel (l_initialized);
1646                                 ig.Emit (OpCodes.Ldsfld, am_cache.Spec.MetaInfo);
1647                         }
1648                 }
1649
1650                 //
1651                 // Look for the best storey for this anonymous method
1652                 //
1653                 AnonymousMethodStorey FindBestMethodStorey ()
1654                 {
1655                         //
1656                         // Use the nearest parent block which has a storey
1657                         //
1658                         for (Block b = Block.Parent; b != null; b = b.Parent) {
1659                                 AnonymousMethodStorey s = b.Explicit.AnonymousMethodStorey;
1660                                 if (s != null)
1661                                         return s;
1662                         }
1663                                         
1664                         return null;
1665                 }
1666
1667                 public override string GetSignatureForError ()
1668                 {
1669                         return TypeManager.CSharpName (type);
1670                 }
1671
1672                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
1673                 {
1674                         type = storey.MutateType (type);
1675                 }
1676
1677                 public static void Reset ()
1678                 {
1679                         unique_id = 0;
1680                 }
1681         }
1682
1683         //
1684         // Anonymous type container
1685         //
1686         public class AnonymousTypeClass : CompilerGeneratedClass
1687         {
1688                 sealed class AnonymousParameters : ParametersCompiled
1689                 {
1690                         public AnonymousParameters (CompilerContext ctx, params Parameter[] parameters)
1691                                 : base (ctx, parameters)
1692                         {
1693                         }
1694
1695                         protected override void ErrorDuplicateName (Parameter p, Report Report)
1696                         {
1697                                 Report.Error (833, p.Location, "`{0}': An anonymous type cannot have multiple properties with the same name",
1698                                         p.Name);
1699                         }
1700                 }
1701
1702                 static int types_counter;
1703                 public const string ClassNamePrefix = "<>__AnonType";
1704                 public const string SignatureForError = "anonymous type";
1705                 
1706                 readonly IList<AnonymousTypeParameter> parameters;
1707
1708                 private AnonymousTypeClass (DeclSpace parent, MemberName name, IList<AnonymousTypeParameter> parameters, Location loc)
1709                         : base (parent, name, (RootContext.EvalMode ? Modifiers.PUBLIC : 0) | Modifiers.SEALED)
1710                 {
1711                         this.parameters = parameters;
1712                 }
1713
1714                 public static AnonymousTypeClass Create (CompilerContext ctx, TypeContainer parent, IList<AnonymousTypeParameter> parameters, Location loc)
1715                 {
1716                         string name = ClassNamePrefix + types_counter++;
1717
1718                         SimpleName [] t_args = new SimpleName [parameters.Count];
1719                         TypeParameterName [] t_params = new TypeParameterName [parameters.Count];
1720                         Parameter [] ctor_params = new Parameter [parameters.Count];
1721                         for (int i = 0; i < parameters.Count; ++i) {
1722                                 AnonymousTypeParameter p = (AnonymousTypeParameter) parameters [i];
1723
1724                                 t_args [i] = new SimpleName ("<" + p.Name + ">__T", p.Location);
1725                                 t_params [i] = new TypeParameterName (t_args [i].Name, null, p.Location);
1726                                 ctor_params [i] = new Parameter (t_args [i], p.Name, 0, null, p.Location);
1727                         }
1728
1729                         //
1730                         // Create generic anonymous type host with generic arguments
1731                         // named upon properties names
1732                         //
1733                         AnonymousTypeClass a_type = new AnonymousTypeClass (parent.NamespaceEntry.SlaveDeclSpace,
1734                                 new MemberName (name, new TypeArguments (t_params), loc), parameters, loc);
1735
1736                         if (parameters.Count > 0)
1737                                 a_type.SetParameterInfo (null);
1738
1739                         Constructor c = new Constructor (a_type, name, Modifiers.PUBLIC | Modifiers.DEBUGGER_HIDDEN,
1740                                 null, new AnonymousParameters (ctx, ctor_params), null, loc);
1741                         c.Block = new ToplevelBlock (ctx, c.Parameters, loc);
1742
1743                         // 
1744                         // Create fields and contructor body with field initialization
1745                         //
1746                         bool error = false;
1747                         for (int i = 0; i < parameters.Count; ++i) {
1748                                 AnonymousTypeParameter p = (AnonymousTypeParameter) parameters [i];
1749
1750                                 Field f = new Field (a_type, t_args [i], Modifiers.PRIVATE | Modifiers.READONLY,
1751                                         new MemberName ("<" + p.Name + ">", p.Location), null);
1752
1753                                 if (!a_type.AddField (f)) {
1754                                         error = true;
1755                                         continue;
1756                                 }
1757
1758                                 c.Block.AddStatement (new StatementExpression (
1759                                         new SimpleAssign (new MemberAccess (new This (p.Location), f.Name),
1760                                                 c.Block.GetParameterReference (p.Name, p.Location))));
1761
1762                                 ToplevelBlock get_block = new ToplevelBlock (ctx, p.Location);
1763                                 get_block.AddStatement (new Return (
1764                                         new MemberAccess (new This (p.Location), f.Name), p.Location));
1765                                 Accessor get_accessor = new Accessor (get_block, 0, null, null, p.Location);
1766                                 Property prop = new Property (a_type, t_args [i], Modifiers.PUBLIC,
1767                                         new MemberName (p.Name, p.Location), null, get_accessor, null, false);
1768                                 a_type.AddProperty (prop);
1769                         }
1770
1771                         if (error)
1772                                 return null;
1773
1774                         a_type.AddConstructor (c);
1775                         return a_type;
1776                 }
1777                 
1778                 public static void Reset ()
1779                 {
1780                         types_counter = 0;
1781                 }
1782
1783                 protected override bool AddToContainer (MemberCore symbol, string name)
1784                 {
1785                         MemberCore mc = GetDefinition (name);
1786
1787                         if (mc == null) {
1788                                 defined_names.Add (name, symbol);
1789                                 return true;
1790                         }
1791
1792                         Report.SymbolRelatedToPreviousError (mc);
1793                         return false;
1794                 }
1795
1796                 protected override bool DoDefineMembers ()
1797                 {
1798                         if (!base.DoDefineMembers ())
1799                                 return false;
1800
1801                         Location loc = Location;
1802
1803                         Method equals = new Method (this, null, TypeManager.system_boolean_expr,
1804                                 Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("Equals", loc),
1805                                 Mono.CSharp.ParametersCompiled.CreateFullyResolved (new Parameter (null, "obj", 0, null, loc), TypeManager.object_type), null);
1806
1807                         Method tostring = new Method (this, null, TypeManager.system_string_expr,
1808                                 Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("ToString", loc),
1809                                 Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null);
1810
1811                         ToplevelBlock equals_block = new ToplevelBlock (Compiler, equals.Parameters, loc);
1812                         TypeExpr current_type;
1813                         if (IsGeneric)
1814                                 current_type = new GenericTypeExpr (this, loc);
1815                         else
1816                                 current_type = new TypeExpression (TypeBuilder, loc);
1817
1818                         equals_block.AddVariable (current_type, "other", loc);
1819                         LocalVariableReference other_variable = new LocalVariableReference (equals_block, "other", loc);
1820
1821                         MemberAccess system_collections_generic = new MemberAccess (new MemberAccess (
1822                                 new QualifiedAliasMember ("global", "System", loc), "Collections", loc), "Generic", loc);
1823
1824                         Expression rs_equals = null;
1825                         Expression string_concat = new StringConstant ("{", loc);
1826                         Expression rs_hashcode = new IntConstant (-2128831035, loc);
1827                         for (int i = 0; i < parameters.Count; ++i) {
1828                                 AnonymousTypeParameter p = (AnonymousTypeParameter) parameters [i];
1829                                 Field f = (Field) Fields [i];
1830
1831                                 MemberAccess equality_comparer = new MemberAccess (new MemberAccess (
1832                                         system_collections_generic, "EqualityComparer",
1833                                                 new TypeArguments (new SimpleName (TypeParameters [i].Name, loc)), loc),
1834                                                 "Default", loc);
1835
1836                                 Arguments arguments_equal = new Arguments (2);
1837                                 arguments_equal.Add (new Argument (new MemberAccess (new This (f.Location), f.Name)));
1838                                 arguments_equal.Add (new Argument (new MemberAccess (other_variable, f.Name)));
1839
1840                                 Expression field_equal = new Invocation (new MemberAccess (equality_comparer,
1841                                         "Equals", loc), arguments_equal);
1842
1843                                 Arguments arguments_hashcode = new Arguments (1);
1844                                 arguments_hashcode.Add (new Argument (new MemberAccess (new This (f.Location), f.Name)));
1845                                 Expression field_hashcode = new Invocation (new MemberAccess (equality_comparer,
1846                                         "GetHashCode", loc), arguments_hashcode);
1847
1848                                 IntConstant FNV_prime = new IntConstant (16777619, loc);                                
1849                                 rs_hashcode = new Binary (Binary.Operator.Multiply,
1850                                         new Binary (Binary.Operator.ExclusiveOr, rs_hashcode, field_hashcode),
1851                                         FNV_prime);
1852
1853                                 Expression field_to_string = new Conditional (new BooleanExpression (new Binary (Binary.Operator.Inequality,
1854                                         new MemberAccess (new This (f.Location), f.Name), new NullLiteral (loc))),
1855                                         new Invocation (new MemberAccess (
1856                                                 new MemberAccess (new This (f.Location), f.Name), "ToString"), null),
1857                                         new StringConstant (string.Empty, loc));
1858
1859                                 if (rs_equals == null) {
1860                                         rs_equals = field_equal;
1861                                         string_concat = new Binary (Binary.Operator.Addition,
1862                                                 string_concat,
1863                                                 new Binary (Binary.Operator.Addition,
1864                                                         new StringConstant (" " + p.Name + " = ", loc),
1865                                                         field_to_string));
1866                                         continue;
1867                                 }
1868
1869                                 //
1870                                 // Implementation of ToString () body using string concatenation
1871                                 //                              
1872                                 string_concat = new Binary (Binary.Operator.Addition,
1873                                         new Binary (Binary.Operator.Addition,
1874                                                 string_concat,
1875                                                 new StringConstant (", " + p.Name + " = ", loc)),
1876                                         field_to_string);
1877
1878                                 rs_equals = new Binary (Binary.Operator.LogicalAnd, rs_equals, field_equal);
1879                         }
1880
1881                         string_concat = new Binary (Binary.Operator.Addition,
1882                                 string_concat,
1883                                 new StringConstant (" }", loc));
1884
1885                         //
1886                         // Equals (object obj) override
1887                         //              
1888                         LocalVariableReference other_variable_assign = new LocalVariableReference (equals_block, "other", loc);
1889                         equals_block.AddStatement (new StatementExpression (
1890                                 new SimpleAssign (other_variable_assign,
1891                                         new As (equals_block.GetParameterReference ("obj", loc),
1892                                                 current_type, loc), loc)));
1893
1894                         Expression equals_test = new Binary (Binary.Operator.Inequality, other_variable, new NullLiteral (loc));
1895                         if (rs_equals != null)
1896                                 equals_test = new Binary (Binary.Operator.LogicalAnd, equals_test, rs_equals);
1897                         equals_block.AddStatement (new Return (equals_test, loc));
1898
1899                         equals.Block = equals_block;
1900                         equals.Define ();
1901                         AddMethod (equals);
1902
1903                         //
1904                         // GetHashCode () override
1905                         //
1906                         Method hashcode = new Method (this, null, TypeManager.system_int32_expr,
1907                                 Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN,
1908                                 new MemberName ("GetHashCode", loc),
1909                                 Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null);
1910
1911                         //
1912                         // Modified FNV with good avalanche behavior and uniform
1913                         // distribution with larger hash sizes.
1914                         //
1915                         // const int FNV_prime = 16777619;
1916                         // int hash = (int) 2166136261;
1917                         // foreach (int d in data)
1918                         //     hash = (hash ^ d) * FNV_prime;
1919                         // hash += hash << 13;
1920                         // hash ^= hash >> 7;
1921                         // hash += hash << 3;
1922                         // hash ^= hash >> 17;
1923                         // hash += hash << 5;
1924
1925                         ToplevelBlock hashcode_top = new ToplevelBlock (Compiler, loc);
1926                         Block hashcode_block = new Block (hashcode_top);
1927                         hashcode_top.AddStatement (new Unchecked (hashcode_block));
1928
1929                         hashcode_block.AddVariable (TypeManager.system_int32_expr, "hash", loc);
1930                         LocalVariableReference hash_variable = new LocalVariableReference (hashcode_block, "hash", loc);
1931                         LocalVariableReference hash_variable_assign = new LocalVariableReference (hashcode_block, "hash", loc);
1932                         hashcode_block.AddStatement (new StatementExpression (
1933                                 new SimpleAssign (hash_variable_assign, rs_hashcode)));
1934
1935                         hashcode_block.AddStatement (new StatementExpression (
1936                                 new CompoundAssign (Binary.Operator.Addition, hash_variable,
1937                                         new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (13, loc)))));
1938                         hashcode_block.AddStatement (new StatementExpression (
1939                                 new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable,
1940                                         new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (7, loc)))));
1941                         hashcode_block.AddStatement (new StatementExpression (
1942                                 new CompoundAssign (Binary.Operator.Addition, hash_variable,
1943                                         new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (3, loc)))));
1944                         hashcode_block.AddStatement (new StatementExpression (
1945                                 new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable,
1946                                         new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (17, loc)))));
1947                         hashcode_block.AddStatement (new StatementExpression (
1948                                 new CompoundAssign (Binary.Operator.Addition, hash_variable,
1949                                         new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (5, loc)))));
1950
1951                         hashcode_block.AddStatement (new Return (hash_variable, loc));
1952                         hashcode.Block = hashcode_top;
1953                         hashcode.Define ();
1954                         AddMethod (hashcode);
1955
1956                         //
1957                         // ToString () override
1958                         //
1959
1960                         ToplevelBlock tostring_block = new ToplevelBlock (Compiler, loc);
1961                         tostring_block.AddStatement (new Return (string_concat, loc));
1962                         tostring.Block = tostring_block;
1963                         tostring.Define ();
1964                         AddMethod (tostring);
1965
1966                         return true;
1967                 }
1968
1969                 public override string GetSignatureForError ()
1970                 {
1971                         return SignatureForError;
1972                 }
1973
1974                 public IList<AnonymousTypeParameter> Parameters {
1975                         get {
1976                                 return parameters;
1977                         }
1978                 }
1979         }
1980 }