Error message formating.
[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 (member_type);
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.FieldBuilder, instace_expr.Type, Location) :
331                                                 new FieldExpr (sf.Field.FieldBuilder, 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.FieldBuilder, 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 MethodInfo MutateGenericMethod (MethodInfo method)
493                 {
494                         Type [] t_args = TypeManager.GetGenericArguments (method);
495                         if (TypeManager.IsGenericType (method.DeclaringType)) {
496                                 Type t = MutateGenericType (method.DeclaringType);
497                                 if (t != method.DeclaringType) {
498                                         method = (MethodInfo) TypeManager.DropGenericMethodArguments (method);
499                                         if (TypeManager.IsBeingCompiled (method))
500                                                 method = TypeBuilder.GetMethod (t, method);
501                                         else
502                                                 method = (MethodInfo) MethodInfo.GetMethodFromHandle (method.MethodHandle, t.TypeHandle);
503                                 }                               
504                         }
505
506                         if (t_args == null || t_args.Length == 0)
507                                 return method;
508
509                         for (int i = 0; i < t_args.Length; ++i)
510                                 t_args [i] = MutateType (t_args [i]);
511
512                         return method.GetGenericMethodDefinition ().MakeGenericMethod (t_args);
513                 }
514
515                 public ConstructorInfo MutateConstructor (ConstructorInfo ctor)
516                 {
517                         if (TypeManager.IsGenericType (ctor.DeclaringType)) {
518                                 Type t = MutateGenericType (ctor.DeclaringType);
519                                 if (t != ctor.DeclaringType) {
520                                         ctor = (ConstructorInfo) TypeManager.DropGenericMethodArguments (ctor);
521                                         if (TypeManager.IsBeingCompiled (ctor))
522                                                 return TypeBuilder.GetConstructor (t, ctor);
523                                                 
524                                         return (ConstructorInfo) ConstructorInfo.GetMethodFromHandle (ctor.MethodHandle, t.TypeHandle);
525                                 }
526                         }
527
528                         return ctor;
529                 }
530                 
531                 public FieldInfo MutateField (FieldInfo field)
532                 {
533                         if (TypeManager.IsGenericType (field.DeclaringType)) {
534                                 Type t = MutateGenericType (field.DeclaringType);
535                                 if (t != field.DeclaringType) {
536                                         field = TypeManager.DropGenericTypeArguments (field.DeclaringType).GetField (field.Name, TypeManager.AllMembers);
537                                         if (TypeManager.IsBeingCompiled (field))
538                                                 return TypeBuilder.GetField (t, field);
539
540                                         return FieldInfo.GetFieldFromHandle (field.FieldHandle, t.TypeHandle);                                          
541                                 }
542                         }
543
544                         return field;
545                 }               
546
547                 protected Type MutateArrayType (Type array)
548                 {
549                         Type element = TypeManager.GetElementType (array);
550                         if (element.IsArray) {
551                                 element = MutateArrayType (element);
552                         } else if (TypeManager.IsGenericParameter (element)) {
553                                 element = MutateGenericArgument (element);
554                         } else if (TypeManager.IsGenericType (element)) {
555                                 element = MutateGenericType (element);
556                         } else {
557                                 return array;
558                         }
559
560                         int rank = array.GetArrayRank ();
561                         if (rank == 1)
562                                 return element.MakeArrayType ();
563
564                         return element.MakeArrayType (rank);
565                 }
566
567                 protected Type MutateGenericType (Type type)
568                 {
569                         Type [] t_args = TypeManager.GetTypeArguments (type);
570                         if (t_args == null || t_args.Length == 0)
571                                 return type;
572
573                         for (int i = 0; i < t_args.Length; ++i)
574                                 t_args [i] = MutateType (t_args [i]);
575
576                         return TypeManager.DropGenericTypeArguments (type).MakeGenericType (t_args);
577                 }
578
579                 //
580                 // Changes method generic argument (MVAR) to type generic argument (VAR)
581                 //
582                 public Type MutateGenericArgument (Type type)
583                 {
584                         if (CurrentTypeParameters != null) {
585                                 TypeParameter tp = TypeParameter.FindTypeParameter (CurrentTypeParameters, type.Name);
586                                 if (tp != null)
587                                         return tp.Type;
588                         }
589
590                         return type;
591                 }
592
593                 public IList<ExplicitBlock> ReferencesFromChildrenBlock {
594                         get { return children_references; }
595                 }
596
597                 public static void Reset ()
598                 {
599                         unique_id = 0;
600                 }               
601         }
602
603         public abstract class HoistedVariable
604         {
605                 //
606                 // Hoisted version of variable references used in expression
607                 // tree has to be delayed until we know its location. The variable
608                 // doesn't know its location until all stories are calculated
609                 //
610                 class ExpressionTreeVariableReference : Expression
611                 {
612                         readonly HoistedVariable hv;
613
614                         public ExpressionTreeVariableReference (HoistedVariable hv)
615                         {
616                                 this.hv = hv;
617                         }
618
619                         public override Expression CreateExpressionTree (ResolveContext ec)
620                         {
621                                 throw new NotSupportedException ("ET");
622                         }
623
624                         protected override Expression DoResolve (ResolveContext ec)
625                         {
626                                 eclass = ExprClass.Value;
627                                 type = TypeManager.expression_type_expr.Type;
628                                 return this;
629                         }
630
631                         public override void Emit (EmitContext ec)
632                         {
633                                 ResolveContext rc = new ResolveContext (ec.MemberContext);
634                                 Expression e = hv.GetFieldExpression (ec).CreateExpressionTree (rc);
635                                 // This should never fail
636                                 e = e.Resolve (rc);
637                                 if (e != null)
638                                         e.Emit (ec);
639                         }
640                 }
641         
642                 protected readonly AnonymousMethodStorey storey;
643                 protected Field field;
644                 Dictionary<AnonymousExpression, FieldExpr> cached_inner_access; // TODO: Hashtable is too heavyweight
645                 FieldExpr cached_outer_access;
646
647                 protected HoistedVariable (AnonymousMethodStorey storey, string name, Type type)
648                         : this (storey, storey.AddCapturedVariable (name, type))
649                 {
650                 }
651
652                 protected HoistedVariable (AnonymousMethodStorey storey, Field field)
653                 {
654                         this.storey = storey;
655                         this.field = field;
656                 }
657
658                 public void AddressOf (EmitContext ec, AddressOp mode)
659                 {
660                         GetFieldExpression (ec).AddressOf (ec, mode);
661                 }
662
663                 public Expression CreateExpressionTree ()
664                 {
665                         return new ExpressionTreeVariableReference (this);
666                 }
667
668                 public void Emit (EmitContext ec)
669                 {
670                         GetFieldExpression (ec).Emit (ec);
671                 }
672
673                 //
674                 // Creates field access expression for hoisted variable
675                 //
676                 protected FieldExpr GetFieldExpression (EmitContext ec)
677                 {
678                         if (ec.CurrentAnonymousMethod == null || ec.CurrentAnonymousMethod.Storey == null) {
679                                 if (cached_outer_access != null)
680                                         return cached_outer_access;
681
682                                 //
683                                 // When setting top-level hoisted variable in generic storey
684                                 // change storey generic types to method generic types (VAR -> MVAR)
685                                 //
686                                 cached_outer_access = storey.MemberName.IsGeneric ?
687                                         new FieldExpr (field.FieldBuilder, storey.Instance.Type, field.Location) :
688                                         new FieldExpr (field.FieldBuilder, field.Location);
689
690                                 cached_outer_access.InstanceExpression = storey.GetStoreyInstanceExpression (ec);
691                                 return cached_outer_access;
692                         }
693
694                         FieldExpr inner_access;
695                         if (cached_inner_access != null) {
696                                 if (!cached_inner_access.TryGetValue (ec.CurrentAnonymousMethod, out inner_access))
697                                         inner_access = null;
698                         } else {
699                                 inner_access = null;
700                                 cached_inner_access = new Dictionary<AnonymousExpression, FieldExpr> (4);
701                         }
702
703                         if (inner_access == null) {
704                                 inner_access = field.Parent.MemberName.IsGeneric ?
705                                         new FieldExpr (field.FieldBuilder, field.Parent.CurrentType, field.Location) :
706                                         new FieldExpr (field.FieldBuilder, field.Location);
707                                                         
708                                 inner_access.InstanceExpression = storey.GetStoreyInstanceExpression (ec);
709                                 cached_inner_access.Add (ec.CurrentAnonymousMethod, inner_access);
710                         }
711
712                         return inner_access;
713                 }
714
715                 public abstract void EmitSymbolInfo ();
716
717                 public void Emit (EmitContext ec, bool leave_copy)
718                 {
719                         GetFieldExpression (ec).Emit (ec, leave_copy);
720                 }
721
722                 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
723                 {
724                         GetFieldExpression (ec).EmitAssign (ec, source, leave_copy, false);
725                 }
726         }
727
728         public class HoistedParameter : HoistedVariable
729         {
730                 sealed class HoistedFieldAssign : Assign
731                 {
732                         public HoistedFieldAssign (Expression target, Expression source)
733                                 : base (target, source, source.Location)
734                         {
735                         }
736
737                         protected override Expression ResolveConversions (ResolveContext ec)
738                         {
739                                 //
740                                 // Implicit conversion check fails for hoisted type arguments
741                                 // as they are of different types (!!0 x !0)
742                                 //
743                                 return this;
744                         }
745                 }
746
747                 readonly ParameterReference parameter;
748
749                 public HoistedParameter (AnonymousMethodStorey scope, ParameterReference par)
750                         : base (scope, par.Name, par.Type)
751                 {
752                         this.parameter = par;
753                 }
754
755                 public HoistedParameter (HoistedParameter hp, string name)
756                         : base (hp.storey, name, hp.parameter.Type)
757                 {
758                         this.parameter = hp.parameter;
759                 }
760
761                 public void EmitHoistingAssignment (EmitContext ec)
762                 {
763                         //
764                         // Remove hoisted redirection to emit assignment from original parameter
765                         //
766                         HoistedVariable temp = parameter.Parameter.HoistedVariant;
767                         parameter.Parameter.HoistedVariant = null;
768
769                         Assign a = new HoistedFieldAssign (GetFieldExpression (ec), parameter);
770                         if (a.Resolve (new ResolveContext (ec.MemberContext)) != null)
771                                 a.EmitStatement (ec);
772
773                         parameter.Parameter.HoistedVariant = temp;
774                 }
775
776                 public override void EmitSymbolInfo ()
777                 {
778                         SymbolWriter.DefineCapturedParameter (storey.ID, field.Name, field.Name);
779                 }
780
781                 public Field Field {
782                         get { return field; }
783                 }
784         }
785
786         class HoistedLocalVariable : HoistedVariable
787         {
788                 readonly string name;
789
790                 public HoistedLocalVariable (AnonymousMethodStorey scope, LocalInfo local, string name)
791                         : base (scope, name, local.VariableType)
792                 {
793                         this.name = local.Name;
794                 }
795
796                 public override void EmitSymbolInfo ()
797                 {
798                         SymbolWriter.DefineCapturedLocal (storey.ID, name, field.Name);
799                 }
800         }
801
802         public class HoistedThis : HoistedVariable
803         {
804                 public HoistedThis (AnonymousMethodStorey storey, Field field)
805                         : base (storey, field)
806                 {
807                 }
808
809                 public void EmitHoistingAssignment (EmitContext ec)
810                 {
811                         SimpleAssign a = new SimpleAssign (GetFieldExpression (ec), new CompilerGeneratedThis (ec.CurrentType, field.Location));
812                         if (a.Resolve (new ResolveContext (ec.MemberContext)) != null)
813                                 a.EmitStatement (ec);
814                 }
815
816                 public override void EmitSymbolInfo ()
817                 {
818                         SymbolWriter.DefineCapturedThis (storey.ID, field.Name);
819                 }
820
821                 public Field Field {
822                         get { return field; }
823                 }
824         }
825
826         //
827         // Anonymous method expression as created by parser
828         //
829         public class AnonymousMethodExpression : Expression
830         {
831                 //
832                 // Special conversion for nested expression tree lambdas
833                 //
834                 class Quote : ShimExpression
835                 {
836                         public Quote (Expression expr)
837                                 : base (expr)
838                         {
839                         }
840
841                         public override Expression CreateExpressionTree (ResolveContext ec)
842                         {
843                                 var args = new Arguments (1);
844                                 args.Add (new Argument (expr.CreateExpressionTree (ec)));
845                                 return CreateExpressionFactoryCall (ec, "Quote", args);
846                         }
847
848                         protected override Expression DoResolve (ResolveContext rc)
849                         {
850                                 expr = expr.Resolve (rc);
851                                 if (expr == null)
852                                         return null;
853
854                                 eclass = expr.eclass;
855                                 type = expr.Type;
856                                 return this;
857                         }
858                 }
859
860                 Dictionary<Type, Expression> compatibles;
861                 public ToplevelBlock Block;
862
863                 public AnonymousMethodExpression (Location loc)
864                 {
865                         this.loc = loc;
866                         this.compatibles = new Dictionary<Type, Expression> ();
867                 }
868
869                 public override string ExprClassName {
870                         get {
871                                 return "anonymous method";
872                         }
873                 }
874
875                 public virtual bool HasExplicitParameters {
876                         get {
877                                 return Parameters != ParametersCompiled.Undefined;
878                         }
879                 }
880                 
881                 public ParametersCompiled Parameters {
882                         get { return Block.Parameters; }
883                 }
884
885                 //
886                 // Returns true if the body of lambda expression can be implicitly
887                 // converted to the delegate of type `delegate_type'
888                 //
889                 public bool ImplicitStandardConversionExists (ResolveContext ec, Type delegate_type)
890                 {
891                         using (ec.With (ResolveContext.Options.InferReturnType, false)) {
892                                 using (ec.Set (ResolveContext.Options.ProbingMode)) {
893                                         return Compatible (ec, delegate_type) != null;
894                                 }
895                         }
896                 }
897
898                 protected Type CompatibleChecks (ResolveContext ec, Type delegate_type)
899                 {
900                         if (TypeManager.IsDelegateType (delegate_type))
901                                 return delegate_type;
902
903                         if (TypeManager.DropGenericTypeArguments (delegate_type) == TypeManager.expression_type) {
904                                 delegate_type = TypeManager.GetTypeArguments (delegate_type) [0];
905                                 if (TypeManager.IsDelegateType (delegate_type))
906                                         return delegate_type;
907
908                                 ec.Report.Error (835, loc, "Cannot convert `{0}' to an expression tree of non-delegate type `{1}'",
909                                         GetSignatureForError (), TypeManager.CSharpName (delegate_type));
910                                 return null;
911                         }
912
913                         ec.Report.Error (1660, loc, "Cannot convert `{0}' to non-delegate type `{1}'",
914                                       GetSignatureForError (), TypeManager.CSharpName (delegate_type));
915                         return null;
916                 }
917
918                 protected bool VerifyExplicitParameters (ResolveContext ec, Type delegate_type, AParametersCollection parameters)
919                 {
920                         if (VerifyParameterCompatibility (ec, delegate_type, parameters, ec.IsInProbingMode))
921                                 return true;
922
923                         if (!ec.IsInProbingMode)
924                                 ec.Report.Error (1661, loc,
925                                         "Cannot convert `{0}' to delegate type `{1}' since there is a parameter mismatch",
926                                         GetSignatureForError (), TypeManager.CSharpName (delegate_type));
927
928                         return false;
929                 }
930
931                 protected bool VerifyParameterCompatibility (ResolveContext ec, Type delegate_type, AParametersCollection invoke_pd, bool ignore_errors)
932                 {
933                         if (Parameters.Count != invoke_pd.Count) {
934                                 if (ignore_errors)
935                                         return false;
936                                 
937                                 ec.Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments",
938                                               TypeManager.CSharpName (delegate_type), Parameters.Count.ToString ());
939                                 return false;
940                         }
941
942                         bool has_implicit_parameters = !HasExplicitParameters;
943                         bool error = false;
944
945                         for (int i = 0; i < Parameters.Count; ++i) {
946                                 Parameter.Modifier p_mod = invoke_pd.FixedParameters [i].ModFlags;
947                                 if (Parameters.FixedParameters [i].ModFlags != p_mod && p_mod != Parameter.Modifier.PARAMS) {
948                                         if (ignore_errors)
949                                                 return false;
950                                         
951                                         if (p_mod == Parameter.Modifier.NONE)
952                                                 ec.Report.Error (1677, loc, "Parameter `{0}' should not be declared with the `{1}' keyword",
953                                                               (i + 1).ToString (), Parameter.GetModifierSignature (Parameters.FixedParameters [i].ModFlags));
954                                         else
955                                                 ec.Report.Error (1676, loc, "Parameter `{0}' must be declared with the `{1}' keyword",
956                                                               (i+1).ToString (), Parameter.GetModifierSignature (p_mod));
957                                         error = true;
958                                 }
959
960                                 if (has_implicit_parameters)
961                                         continue;
962
963                                 Type type = invoke_pd.Types [i];
964                                 
965                                 // We assume that generic parameters are always inflated
966                                 if (TypeManager.IsGenericParameter (type))
967                                         continue;
968                                 
969                                 if (TypeManager.HasElementType (type) && TypeManager.IsGenericParameter (TypeManager.GetElementType (type)))
970                                         continue;
971                                 
972                                 if (invoke_pd.Types [i] != Parameters.Types [i]) {
973                                         if (ignore_errors)
974                                                 return false;
975                                         
976                                         ec.Report.Error (1678, loc, "Parameter `{0}' is declared as type `{1}' but should be `{2}'",
977                                                       (i+1).ToString (),
978                                                       TypeManager.CSharpName (Parameters.Types [i]),
979                                                       TypeManager.CSharpName (invoke_pd.Types [i]));
980                                         error = true;
981                                 }
982                         }
983
984                         return !error;
985                 }
986
987                 //
988                 // Infers type arguments based on explicit arguments
989                 //
990                 public bool ExplicitTypeInference (ResolveContext ec, TypeInferenceContext type_inference, Type delegate_type)
991                 {
992                         if (!HasExplicitParameters)
993                                 return false;
994
995                         if (!TypeManager.IsDelegateType (delegate_type)) {
996                                 if (TypeManager.DropGenericTypeArguments (delegate_type) != TypeManager.expression_type)
997                                         return false;
998
999                                 delegate_type = TypeManager.GetTypeArguments (delegate_type) [0];
1000                                 if (!TypeManager.IsDelegateType (delegate_type))
1001                                         return false;
1002                         }
1003                         
1004                         AParametersCollection d_params = TypeManager.GetDelegateParameters (ec, delegate_type);
1005                         if (d_params.Count != Parameters.Count)
1006                                 return false;
1007
1008                         for (int i = 0; i < Parameters.Count; ++i) {
1009                                 Type itype = d_params.Types [i];
1010                                 if (!TypeManager.IsGenericParameter (itype)) {
1011                                         if (!TypeManager.HasElementType (itype))
1012                                                 continue;
1013                                         
1014                                         if (!TypeManager.IsGenericParameter (TypeManager.GetElementType (itype)))
1015                                             continue;
1016                                 }
1017                                 type_inference.ExactInference (Parameters.Types [i], itype);
1018                         }
1019                         return true;
1020                 }
1021
1022                 public Type InferReturnType (ResolveContext ec, TypeInferenceContext tic, Type delegate_type)
1023                 {
1024                         AnonymousExpression am;
1025                         using (ec.Set (ResolveContext.Options.ProbingMode | ResolveContext.Options.InferReturnType)) {
1026                                 am = CompatibleMethodBody (ec, tic, InternalType.Arglist, delegate_type);
1027                                 if (am != null)
1028                                         am = am.Compatible (ec);
1029                         }
1030                         
1031                         if (am == null)
1032                                 return null;
1033
1034                         return am.ReturnType;
1035                 }
1036
1037                 //
1038                 // Returns AnonymousMethod container if this anonymous method
1039                 // expression can be implicitly converted to the delegate type `delegate_type'
1040                 //
1041                 public Expression Compatible (ResolveContext ec, Type type)
1042                 {
1043                         Expression am;
1044                         if (compatibles.TryGetValue (type, out am))
1045                                 return am;
1046
1047                         Type delegate_type = CompatibleChecks (ec, type);
1048                         if (delegate_type == null)
1049                                 return null;
1050
1051                         //
1052                         // At this point its the first time we know the return type that is 
1053                         // needed for the anonymous method.  We create the method here.
1054                         //
1055
1056                         MethodInfo invoke_mb = Delegate.GetInvokeMethod (ec.Compiler,
1057                                 ec.CurrentType, delegate_type);
1058                         Type return_type = TypeManager.TypeToCoreType (invoke_mb.ReturnType);
1059
1060 #if MS_COMPATIBLE
1061                         Type[] g_args = delegate_type.GetGenericArguments ();
1062                         if (return_type.IsGenericParameter)
1063                                 return_type = g_args [return_type.GenericParameterPosition];
1064 #endif
1065
1066                         //
1067                         // Second: the return type of the delegate must be compatible with 
1068                         // the anonymous type.   Instead of doing a pass to examine the block
1069                         // we satisfy the rule by setting the return type on the EmitContext
1070                         // to be the delegate type return type.
1071                         //
1072
1073                         var body = CompatibleMethodBody (ec, null, return_type, delegate_type);
1074                         if (body == null)
1075                                 return null;
1076
1077                         bool etree_conversion = delegate_type != type;
1078
1079                         try {
1080                                 if (etree_conversion) {
1081                                         if (ec.HasSet (ResolveContext.Options.ExpressionTreeConversion)) {
1082                                                 //
1083                                                 // Nested expression tree lambda use same scope as parent
1084                                                 // lambda, this also means no variable capturing between this
1085                                                 // and parent scope
1086                                                 //
1087                                                 am = body.Compatible (ec, ec.CurrentAnonymousMethod);
1088
1089                                                 //
1090                                                 // Quote nested expression tree
1091                                                 //
1092                                                 if (am != null)
1093                                                         am = new Quote (am);
1094                                         } else {
1095                                                 int errors = ec.Report.Errors;
1096
1097                                                 using (ec.Set (ResolveContext.Options.ExpressionTreeConversion)) {
1098                                                         am = body.Compatible (ec);
1099                                                 }
1100
1101                                                 //
1102                                                 // Rewrite expressions into expression tree when targeting Expression<T>
1103                                                 //
1104                                                 if (am != null && errors == ec.Report.Errors)
1105                                                         am = CreateExpressionTree (ec, delegate_type);
1106                                         }
1107                                 } else {
1108                                         am = body.Compatible (ec);
1109                                 }
1110                         } catch (CompletionResult) {
1111                                 throw;
1112                         } catch (Exception e) {
1113                                 throw new InternalErrorException (e, loc);
1114                         }
1115                         
1116                         if (!ec.IsInProbingMode)
1117                                 compatibles.Add (type, am == null ? EmptyExpression.Null : am);
1118
1119                         return am;
1120                 }
1121
1122                 protected virtual Expression CreateExpressionTree (ResolveContext ec, Type delegate_type)
1123                 {
1124                         return CreateExpressionTree (ec);
1125                 }
1126
1127                 public override Expression CreateExpressionTree (ResolveContext ec)
1128                 {
1129                         ec.Report.Error (1946, loc, "An anonymous method cannot be converted to an expression tree");
1130                         return null;
1131                 }
1132
1133                 protected virtual ParametersCompiled ResolveParameters (ResolveContext ec, TypeInferenceContext tic, Type delegate_type)
1134                 {
1135                         AParametersCollection delegate_parameters = TypeManager.GetDelegateParameters (ec, delegate_type);
1136
1137                         if (Parameters == ParametersCompiled.Undefined) {
1138                                 //
1139                                 // We provide a set of inaccessible parameters
1140                                 //
1141                                 Parameter[] fixedpars = new Parameter[delegate_parameters.Count];
1142
1143                                 for (int i = 0; i < delegate_parameters.Count; i++) {
1144                                         Parameter.Modifier i_mod = delegate_parameters.FixedParameters [i].ModFlags;
1145                                         if (i_mod == Parameter.Modifier.OUT) {
1146                                                 ec.Report.Error (1688, loc, "Cannot convert anonymous " +
1147                                                                   "method block without a parameter list " +
1148                                                                   "to delegate type `{0}' because it has " +
1149                                                                   "one or more `out' parameters.",
1150                                                                   TypeManager.CSharpName (delegate_type));
1151                                                 return null;
1152                                         }
1153                                         fixedpars[i] = new Parameter (
1154                                                 null, null,
1155                                                 delegate_parameters.FixedParameters [i].ModFlags, null, loc);
1156                                 }
1157
1158                                 return ParametersCompiled.CreateFullyResolved (fixedpars, delegate_parameters.Types);
1159                         }
1160
1161                         if (!VerifyExplicitParameters (ec, delegate_type, delegate_parameters)) {
1162                                 return null;
1163                         }
1164
1165                         return Parameters;
1166                 }
1167
1168                 protected override Expression DoResolve (ResolveContext ec)
1169                 {
1170                         if (ec.HasSet (ResolveContext.Options.ConstantScope)) {
1171                                 ec.Report.Error (1706, loc, "Anonymous methods and lambda expressions cannot be used in the current context");
1172                                 return null;
1173                         }
1174
1175                         //
1176                         // Set class type, set type
1177                         //
1178
1179                         eclass = ExprClass.Value;
1180
1181                         //
1182                         // This hack means `The type is not accessible
1183                         // anywhere', we depend on special conversion
1184                         // rules.
1185                         // 
1186                         type = InternalType.AnonymousMethod;
1187
1188                         if ((Parameters != null) && !Parameters.Resolve (ec))
1189                                 return null;
1190
1191                         // FIXME: The emitted code isn't very careful about reachability
1192                         // so, ensure we have a 'ret' at the end
1193                         BlockContext bc = ec as BlockContext;
1194                         if (bc != null && bc.CurrentBranching != null && bc.CurrentBranching.CurrentUsageVector.IsUnreachable)
1195                                 bc.NeedReturnLabel ();
1196
1197                         return this;
1198                 }
1199
1200                 public override void Emit (EmitContext ec)
1201                 {
1202                         // nothing, as we only exist to not do anything.
1203                 }
1204
1205                 public static void Error_AddressOfCapturedVar (ResolveContext ec, IVariableReference var, Location loc)
1206                 {
1207                         ec.Report.Error (1686, loc,
1208                                 "Local variable or parameter `{0}' cannot have their address taken and be used inside an anonymous method or lambda expression",
1209                                 var.Name);
1210                 }
1211
1212                 public override string GetSignatureForError ()
1213                 {
1214                         return ExprClassName;
1215                 }
1216
1217                 AnonymousMethodBody CompatibleMethodBody (ResolveContext ec, TypeInferenceContext tic, Type return_type, Type delegate_type)
1218                 {
1219                         ParametersCompiled p = ResolveParameters (ec, tic, delegate_type);
1220                         if (p == null)
1221                                 return null;
1222
1223                         ToplevelBlock b = ec.IsInProbingMode ? (ToplevelBlock) Block.PerformClone () : Block;
1224
1225                         return CompatibleMethodFactory (return_type, delegate_type, p, b);
1226
1227                 }
1228
1229                 protected virtual AnonymousMethodBody CompatibleMethodFactory (Type return_type, Type delegate_type, ParametersCompiled p, ToplevelBlock b)
1230                 {
1231                         return new AnonymousMethodBody (p, b, return_type, delegate_type, loc);
1232                 }
1233
1234                 protected override void CloneTo (CloneContext clonectx, Expression t)
1235                 {
1236                         AnonymousMethodExpression target = (AnonymousMethodExpression) t;
1237
1238                         target.Block = (ToplevelBlock) clonectx.LookupBlock (Block);
1239                 }
1240         }
1241
1242         //
1243         // Abstract expression for any block which requires variables hoisting
1244         //
1245         public abstract class AnonymousExpression : Expression
1246         {
1247                 protected class AnonymousMethodMethod : Method
1248                 {
1249                         public readonly AnonymousExpression AnonymousMethod;
1250                         public readonly AnonymousMethodStorey Storey;
1251                         readonly string RealName;
1252
1253                         public AnonymousMethodMethod (DeclSpace parent, AnonymousExpression am, AnonymousMethodStorey storey,
1254                                                           GenericMethod generic, TypeExpr return_type,
1255                                                           Modifiers mod, string real_name, MemberName name,
1256                                                           ParametersCompiled parameters)
1257                                 : base (parent, generic, return_type, mod | Modifiers.COMPILER_GENERATED,
1258                                                 name, parameters, null)
1259                         {
1260                                 this.AnonymousMethod = am;
1261                                 this.Storey = storey;
1262                                 this.RealName = real_name;
1263
1264                                 Parent.PartialContainer.AddMethod (this);
1265                                 Block = am.Block;
1266                         }
1267
1268                         public override EmitContext CreateEmitContext (ILGenerator ig)
1269                         {
1270                                 EmitContext ec = new EmitContext (this, ig, ReturnType);
1271                                 ec.CurrentAnonymousMethod = AnonymousMethod;
1272                                 if (AnonymousMethod.return_label != null) {
1273                                         ec.HasReturnLabel = true;
1274                                         ec.ReturnLabel = (Label) AnonymousMethod.return_label;
1275                                 }
1276
1277                                 return ec;
1278                         }
1279
1280                         protected override bool ResolveMemberType ()
1281                         {
1282                                 if (!base.ResolveMemberType ())
1283                                         return false;
1284
1285                                 if (Storey != null && Storey.IsGeneric) {
1286                                         AnonymousMethodStorey gstorey = Storey.GetGenericStorey ();
1287                                         if (gstorey != null) {
1288                                                 if (!Parameters.IsEmpty) {
1289                                                         Type [] ptypes = Parameters.Types;
1290                                                         for (int i = 0; i < ptypes.Length; ++i)
1291                                                                 ptypes [i] = gstorey.MutateType (ptypes [i]);
1292                                                 }
1293
1294                                                 member_type = gstorey.MutateType (member_type);
1295                                         }
1296                                 }
1297
1298                                 return true;
1299                         }
1300
1301                         public override void Emit ()
1302                         {
1303                                 //
1304                                 // Before emitting any code we have to change all MVAR references to VAR
1305                                 // when the method is of generic type and has hoisted variables
1306                                 //
1307                                 if (Storey == Parent && Storey.IsGeneric) {
1308                                         AnonymousMethodStorey gstorey = Storey.GetGenericStorey ();
1309                                         if (gstorey != null) {
1310                                                 block.MutateHoistedGenericType (gstorey);
1311                                         }
1312                                 }
1313
1314                                 if (MethodBuilder == null) {
1315                                         Define ();
1316                                 }
1317
1318                                 base.Emit ();
1319                         }
1320
1321                         public override void EmitExtraSymbolInfo (SourceMethod source)
1322                         {
1323                                 source.SetRealMethodName (RealName);
1324                         }
1325                 }
1326
1327                 readonly ToplevelBlock block;
1328
1329                 public Type ReturnType;
1330
1331                 object return_label;
1332
1333                 protected AnonymousExpression (ToplevelBlock block, Type return_type, Location loc)
1334                 {
1335                         this.ReturnType = return_type;
1336                         this.block = block;
1337                         this.loc = loc;
1338                 }
1339
1340                 public abstract string ContainerType { get; }
1341                 public abstract bool IsIterator { get; }
1342                 public abstract AnonymousMethodStorey Storey { get; }
1343
1344                 public AnonymousExpression Compatible (ResolveContext ec)
1345                 {
1346                         return Compatible (ec, this);
1347                 }
1348
1349                 public AnonymousExpression Compatible (ResolveContext ec, AnonymousExpression ae)
1350                 {
1351                         // TODO: Implement clone
1352                         BlockContext aec = new BlockContext (ec.MemberContext, Block, ReturnType);
1353                         aec.CurrentAnonymousMethod = ae;
1354
1355                         IDisposable aec_dispose = null;
1356                         ResolveContext.Options flags = 0;
1357                         if (ec.HasSet (ResolveContext.Options.InferReturnType)) {
1358                                 flags |= ResolveContext.Options.InferReturnType;
1359                                 aec.ReturnTypeInference = new TypeInferenceContext ();
1360                         }
1361
1362                         if (ec.IsInProbingMode)
1363                                 flags |= ResolveContext.Options.ProbingMode;
1364
1365                         if (ec.HasSet (ResolveContext.Options.FieldInitializerScope))
1366                                 flags |= ResolveContext.Options.FieldInitializerScope;
1367
1368                         if (ec.IsUnsafe)
1369                                 flags |= ResolveContext.Options.UnsafeScope;
1370
1371                         if (ec.HasSet (ResolveContext.Options.CheckedScope))
1372                                 flags |= ResolveContext.Options.CheckedScope;
1373
1374                         if (ec.HasSet (ResolveContext.Options.ExpressionTreeConversion))
1375                                 flags |= ResolveContext.Options.ExpressionTreeConversion;
1376
1377                         // HACK: Flag with 0 cannot be set 
1378                         if (flags != 0)
1379                                 aec_dispose = aec.Set (flags);
1380
1381                         bool res = Block.Resolve (ec.CurrentBranching, aec, Block.Parameters, null);
1382
1383                         if (aec.HasReturnLabel)
1384                                 return_label = aec.ReturnLabel;
1385
1386                         if (ec.HasSet (ResolveContext.Options.InferReturnType)) {
1387                                 aec.ReturnTypeInference.FixAllTypes (ec);
1388                                 ReturnType = aec.ReturnTypeInference.InferredTypeArguments [0];
1389                         }
1390
1391                         if (aec_dispose != null) {
1392                                 aec_dispose.Dispose ();
1393                         }
1394
1395                         return res ? this : null;
1396                 }
1397
1398                 public void SetHasThisAccess ()
1399                 {
1400                         Block.HasCapturedThis = true;
1401                         ExplicitBlock b = Block.Parent.Explicit;
1402
1403                         while (b != null) {
1404                                 if (b.HasCapturedThis)
1405                                         return;
1406
1407                                 b.HasCapturedThis = true;
1408                                 b = b.Parent == null ? null : b.Parent.Explicit;
1409                         }
1410                 }
1411
1412                 //
1413                 // The block that makes up the body for the anonymous method
1414                 //
1415                 public ToplevelBlock Block {
1416                         get {
1417                                 return block;
1418                         }
1419                 }
1420
1421         }
1422
1423         public class AnonymousMethodBody : AnonymousExpression
1424         {
1425                 protected readonly ParametersCompiled parameters;
1426                 AnonymousMethodStorey storey;
1427
1428                 AnonymousMethodMethod method;
1429                 Field am_cache;
1430                 string block_name;
1431
1432                 static int unique_id;
1433
1434                 public AnonymousMethodBody (ParametersCompiled parameters,
1435                                         ToplevelBlock block, Type return_type, Type delegate_type,
1436                                         Location loc)
1437                         : base (block, return_type, loc)
1438                 {
1439                         this.type = delegate_type;
1440                         this.parameters = parameters;
1441                 }
1442
1443                 public override string ContainerType {
1444                         get { return "anonymous method"; }
1445                 }
1446
1447                 public override AnonymousMethodStorey Storey {
1448                         get { return storey; }
1449                 }
1450
1451                 public override bool IsIterator {
1452                         get { return false; }
1453                 }
1454
1455                 public override Expression CreateExpressionTree (ResolveContext ec)
1456                 {
1457                         ec.Report.Error (1945, loc, "An expression tree cannot contain an anonymous method expression");
1458                         return null;
1459                 }
1460
1461                 bool Define (ResolveContext ec)
1462                 {
1463                         if (!Block.Resolved && Compatible (ec) == null)
1464                                 return false;
1465
1466                         if (block_name == null) {
1467                                 MemberCore mc = (MemberCore) ec.MemberContext;
1468                                 block_name = mc.MemberName.Basename;
1469                         }
1470
1471                         return true;
1472                 }
1473
1474                 //
1475                 // Creates a host for the anonymous method
1476                 //
1477                 AnonymousMethodMethod DoCreateMethodHost (EmitContext ec)
1478                 {
1479                         //
1480                         // Anonymous method body can be converted to
1481                         //
1482                         // 1, an instance method in current scope when only `this' is hoisted
1483                         // 2, a static method in current scope when neither `this' nor any variable is hoisted
1484                         // 3, an instance method in compiler generated storey when any hoisted variable exists
1485                         //
1486
1487                         Modifiers modifiers;
1488                         if (Block.HasCapturedVariable || Block.HasCapturedThis) {
1489                                 storey = FindBestMethodStorey ();
1490                                 modifiers = storey != null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
1491                         } else {
1492                                 if (ec.CurrentAnonymousMethod != null)
1493                                         storey = ec.CurrentAnonymousMethod.Storey;
1494
1495                                 modifiers = Modifiers.STATIC | Modifiers.PRIVATE;
1496                         }
1497
1498                         TypeContainer parent = storey != null ? storey : ec.CurrentTypeDefinition;
1499
1500                         MemberCore mc = ec.MemberContext as MemberCore;
1501                         string name = CompilerGeneratedClass.MakeName (parent != storey ? block_name : null,
1502                                 "m", null, unique_id++);
1503
1504                         MemberName member_name;
1505                         GenericMethod generic_method;
1506                         if (storey == null && mc.MemberName.TypeArguments != null) {
1507                                 member_name = new MemberName (name, mc.MemberName.TypeArguments.Clone (), Location);
1508
1509                                 generic_method = new GenericMethod (parent.NamespaceEntry, parent, member_name,
1510                                         new TypeExpression (ReturnType, Location), parameters);
1511
1512                                 var list = new List<Constraints> ();
1513                                 foreach (TypeParameter tparam in ec.CurrentTypeParameters) {
1514                                         if (tparam.Constraints != null)
1515                                                 list.Add (tparam.Constraints.Clone ());
1516                                 }
1517                                 generic_method.SetParameterInfo (list);
1518                         } else {
1519                                 member_name = new MemberName (name, Location);
1520                                 generic_method = null;
1521                         }
1522
1523                         string real_name = String.Format (
1524                                 "{0}~{1}{2}", mc.GetSignatureForError (), GetSignatureForError (),
1525                                 parameters.GetSignatureForError ());
1526
1527                         return new AnonymousMethodMethod (parent,
1528                                 this, storey, generic_method, new TypeExpression (ReturnType, Location), modifiers,
1529                                 real_name, member_name, parameters);
1530                 }
1531
1532                 protected override Expression DoResolve (ResolveContext ec)
1533                 {
1534                         if (!Define (ec))
1535                                 return null;
1536
1537                         eclass = ExprClass.Value;
1538                         return this;
1539                 }
1540
1541                 public override void Emit (EmitContext ec)
1542                 {
1543                         //
1544                         // Use same anonymous method implementation for scenarios where same
1545                         // code is used from multiple blocks, e.g. field initializers
1546                         //
1547                         if (method == null) {
1548                                 //
1549                                 // Delay an anonymous method definition to avoid emitting unused code
1550                                 // for unreachable blocks or expression trees
1551                                 //
1552                                 method = DoCreateMethodHost (ec);
1553                                 method.Define ();
1554                         }
1555
1556                         bool is_static = (method.ModFlags & Modifiers.STATIC) != 0;
1557                         if (is_static && am_cache == null) {
1558                                 //
1559                                 // Creates a field cache to store delegate instance if it's not generic
1560                                 //
1561                                 if (!method.MemberName.IsGeneric) {
1562                                         TypeContainer parent = method.Parent.PartialContainer;
1563                                         int id = parent.Fields == null ? 0 : parent.Fields.Count;
1564                                         am_cache = new Field (parent, new TypeExpression (type, loc),
1565                                                 Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED,
1566                                                 new MemberName (CompilerGeneratedClass.MakeName (null, "f", "am$cache", id), loc), null);
1567                                         am_cache.Define ();
1568                                         parent.AddField (am_cache);
1569                                 } else {
1570                                         // TODO: Implement caching of generated generic static methods
1571                                         //
1572                                         // Idea:
1573                                         //
1574                                         // Some extra class is needed to capture variable generic type
1575                                         // arguments. Maybe we could re-use anonymous types, with a unique
1576                                         // anonymous method id, but they are quite heavy.
1577                                         //
1578                                         // Consider : "() => typeof(T);"
1579                                         //
1580                                         // We need something like
1581                                         // static class Wrap<Tn, Tm, DelegateType> {
1582                                         //              public static DelegateType cache;
1583                                         // }
1584                                         //
1585                                         // We then specialize local variable to capture all generic parameters
1586                                         // and delegate type, e.g. "Wrap<Ta, Tb, DelegateTypeInst> cache;"
1587                                         //
1588                                 }
1589                         }
1590
1591                         ILGenerator ig = ec.ig;
1592                         Label l_initialized = ig.DefineLabel ();
1593
1594                         if (am_cache != null) {
1595                                 ig.Emit (OpCodes.Ldsfld, am_cache.FieldBuilder);
1596                                 ig.Emit (OpCodes.Brtrue_S, l_initialized);
1597                         }
1598
1599                         //
1600                         // Load method delegate implementation
1601                         //
1602
1603                         if (is_static) {
1604                                 ig.Emit (OpCodes.Ldnull);
1605                         } else if (storey != null) {
1606                                 Expression e = storey.GetStoreyInstanceExpression (ec).Resolve (new ResolveContext (ec.MemberContext));
1607                                 if (e != null)
1608                                         e.Emit (ec);
1609                         } else {
1610                                 ig.Emit (OpCodes.Ldarg_0);
1611                         }
1612
1613                         MethodInfo delegate_method = method.MethodBuilder;
1614                         if (storey != null && storey.MemberName.IsGeneric) {
1615                                 Type t = storey.Instance.Type;
1616                                 
1617                                 //
1618                                 // Mutate anonymous method instance type if we are in nested
1619                                 // hoisted generic anonymous method storey
1620                                 //
1621                                 if (ec.CurrentAnonymousMethod != null &&
1622                                         ec.CurrentAnonymousMethod.Storey != null &&
1623                                         ec.CurrentAnonymousMethod.Storey.IsGeneric) {
1624                                         t = storey.GetGenericStorey ().MutateType (t);
1625                                 }
1626
1627                                 delegate_method = TypeBuilder.GetMethod (t, delegate_method);
1628                         }
1629
1630                         ig.Emit (OpCodes.Ldftn, delegate_method);
1631
1632                         ConstructorInfo constructor_method = Delegate.GetConstructor (ec.MemberContext.Compiler, ec.CurrentType, type);
1633 #if MS_COMPATIBLE
1634             if (type.IsGenericType && type is TypeBuilder)
1635                 constructor_method = TypeBuilder.GetConstructor (type, constructor_method);
1636 #endif
1637                         ig.Emit (OpCodes.Newobj, constructor_method);
1638
1639                         if (am_cache != null) {
1640                                 ig.Emit (OpCodes.Stsfld, am_cache.FieldBuilder);
1641                                 ig.MarkLabel (l_initialized);
1642                                 ig.Emit (OpCodes.Ldsfld, am_cache.FieldBuilder);
1643                         }
1644                 }
1645
1646                 //
1647                 // Look for the best storey for this anonymous method
1648                 //
1649                 AnonymousMethodStorey FindBestMethodStorey ()
1650                 {
1651                         //
1652                         // Use the nearest parent block which has a storey
1653                         //
1654                         for (Block b = Block.Parent; b != null; b = b.Parent) {
1655                                 AnonymousMethodStorey s = b.Explicit.AnonymousMethodStorey;
1656                                 if (s != null)
1657                                         return s;
1658                         }
1659                                         
1660                         return null;
1661                 }
1662
1663                 public override string GetSignatureForError ()
1664                 {
1665                         return TypeManager.CSharpName (type);
1666                 }
1667
1668                 public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
1669                 {
1670                         type = storey.MutateType (type);
1671                 }
1672
1673                 public static void Reset ()
1674                 {
1675                         unique_id = 0;
1676                 }
1677         }
1678
1679         //
1680         // Anonymous type container
1681         //
1682         public class AnonymousTypeClass : CompilerGeneratedClass
1683         {
1684                 sealed class AnonymousParameters : ParametersCompiled
1685                 {
1686                         public AnonymousParameters (CompilerContext ctx, params Parameter[] parameters)
1687                                 : base (ctx, parameters)
1688                         {
1689                         }
1690
1691                         protected override void ErrorDuplicateName (Parameter p, Report Report)
1692                         {
1693                                 Report.Error (833, p.Location, "`{0}': An anonymous type cannot have multiple properties with the same name",
1694                                         p.Name);
1695                         }
1696                 }
1697
1698                 static int types_counter;
1699                 public const string ClassNamePrefix = "<>__AnonType";
1700                 public const string SignatureForError = "anonymous type";
1701                 
1702                 readonly IList<AnonymousTypeParameter> parameters;
1703
1704                 private AnonymousTypeClass (DeclSpace parent, MemberName name, IList<AnonymousTypeParameter> parameters, Location loc)
1705                         : base (parent, name, (RootContext.EvalMode ? Modifiers.PUBLIC : 0) | Modifiers.SEALED)
1706                 {
1707                         this.parameters = parameters;
1708                 }
1709
1710                 public static AnonymousTypeClass Create (CompilerContext ctx, TypeContainer parent, IList<AnonymousTypeParameter> parameters, Location loc)
1711                 {
1712                         string name = ClassNamePrefix + types_counter++;
1713
1714                         SimpleName [] t_args = new SimpleName [parameters.Count];
1715                         TypeParameterName [] t_params = new TypeParameterName [parameters.Count];
1716                         Parameter [] ctor_params = new Parameter [parameters.Count];
1717                         for (int i = 0; i < parameters.Count; ++i) {
1718                                 AnonymousTypeParameter p = (AnonymousTypeParameter) parameters [i];
1719
1720                                 t_args [i] = new SimpleName ("<" + p.Name + ">__T", p.Location);
1721                                 t_params [i] = new TypeParameterName (t_args [i].Name, null, p.Location);
1722                                 ctor_params [i] = new Parameter (t_args [i], p.Name, 0, null, p.Location);
1723                         }
1724
1725                         //
1726                         // Create generic anonymous type host with generic arguments
1727                         // named upon properties names
1728                         //
1729                         AnonymousTypeClass a_type = new AnonymousTypeClass (parent.NamespaceEntry.SlaveDeclSpace,
1730                                 new MemberName (name, new TypeArguments (t_params), loc), parameters, loc);
1731
1732                         if (parameters.Count > 0)
1733                                 a_type.SetParameterInfo (null);
1734
1735                         Constructor c = new Constructor (a_type, name, Modifiers.PUBLIC | Modifiers.DEBUGGER_HIDDEN,
1736                                 null, new AnonymousParameters (ctx, ctor_params), null, loc);
1737                         c.Block = new ToplevelBlock (ctx, c.Parameters, loc);
1738
1739                         // 
1740                         // Create fields and contructor body with field initialization
1741                         //
1742                         bool error = false;
1743                         for (int i = 0; i < parameters.Count; ++i) {
1744                                 AnonymousTypeParameter p = (AnonymousTypeParameter) parameters [i];
1745
1746                                 Field f = new Field (a_type, t_args [i], Modifiers.PRIVATE | Modifiers.READONLY,
1747                                         new MemberName ("<" + p.Name + ">", p.Location), null);
1748
1749                                 if (!a_type.AddField (f)) {
1750                                         error = true;
1751                                         continue;
1752                                 }
1753
1754                                 c.Block.AddStatement (new StatementExpression (
1755                                         new SimpleAssign (new MemberAccess (new This (p.Location), f.Name),
1756                                                 c.Block.GetParameterReference (p.Name, p.Location))));
1757
1758                                 ToplevelBlock get_block = new ToplevelBlock (ctx, p.Location);
1759                                 get_block.AddStatement (new Return (
1760                                         new MemberAccess (new This (p.Location), f.Name), p.Location));
1761                                 Accessor get_accessor = new Accessor (get_block, 0, null, null, p.Location);
1762                                 Property prop = new Property (a_type, t_args [i], Modifiers.PUBLIC,
1763                                         new MemberName (p.Name, p.Location), null, get_accessor, null, false);
1764                                 a_type.AddProperty (prop);
1765                         }
1766
1767                         if (error)
1768                                 return null;
1769
1770                         a_type.AddConstructor (c);
1771                         return a_type;
1772                 }
1773                 
1774                 public static void Reset ()
1775                 {
1776                         types_counter = 0;
1777                 }
1778
1779                 protected override bool AddToContainer (MemberCore symbol, string name)
1780                 {
1781                         MemberCore mc = GetDefinition (name);
1782
1783                         if (mc == null) {
1784                                 defined_names.Add (name, symbol);
1785                                 return true;
1786                         }
1787
1788                         Report.SymbolRelatedToPreviousError (mc);
1789                         return false;
1790                 }
1791
1792                 protected override bool DoDefineMembers ()
1793                 {
1794                         if (!base.DoDefineMembers ())
1795                                 return false;
1796
1797                         Location loc = Location;
1798
1799                         Method equals = new Method (this, null, TypeManager.system_boolean_expr,
1800                                 Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("Equals", loc),
1801                                 Mono.CSharp.ParametersCompiled.CreateFullyResolved (new Parameter (null, "obj", 0, null, loc), TypeManager.object_type), null);
1802
1803                         Method tostring = new Method (this, null, TypeManager.system_string_expr,
1804                                 Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("ToString", loc),
1805                                 Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null);
1806
1807                         ToplevelBlock equals_block = new ToplevelBlock (Compiler, equals.Parameters, loc);
1808                         TypeExpr current_type;
1809                         if (IsGeneric)
1810                                 current_type = new GenericTypeExpr (this, loc);
1811                         else
1812                                 current_type = new TypeExpression (TypeBuilder, loc);
1813
1814                         equals_block.AddVariable (current_type, "other", loc);
1815                         LocalVariableReference other_variable = new LocalVariableReference (equals_block, "other", loc);
1816
1817                         MemberAccess system_collections_generic = new MemberAccess (new MemberAccess (
1818                                 new QualifiedAliasMember ("global", "System", loc), "Collections", loc), "Generic", loc);
1819
1820                         Expression rs_equals = null;
1821                         Expression string_concat = new StringConstant ("{", loc);
1822                         Expression rs_hashcode = new IntConstant (-2128831035, loc);
1823                         for (int i = 0; i < parameters.Count; ++i) {
1824                                 AnonymousTypeParameter p = (AnonymousTypeParameter) parameters [i];
1825                                 Field f = (Field) Fields [i];
1826
1827                                 MemberAccess equality_comparer = new MemberAccess (new MemberAccess (
1828                                         system_collections_generic, "EqualityComparer",
1829                                                 new TypeArguments (new SimpleName (TypeParameters [i].Name, loc)), loc),
1830                                                 "Default", loc);
1831
1832                                 Arguments arguments_equal = new Arguments (2);
1833                                 arguments_equal.Add (new Argument (new MemberAccess (new This (f.Location), f.Name)));
1834                                 arguments_equal.Add (new Argument (new MemberAccess (other_variable, f.Name)));
1835
1836                                 Expression field_equal = new Invocation (new MemberAccess (equality_comparer,
1837                                         "Equals", loc), arguments_equal);
1838
1839                                 Arguments arguments_hashcode = new Arguments (1);
1840                                 arguments_hashcode.Add (new Argument (new MemberAccess (new This (f.Location), f.Name)));
1841                                 Expression field_hashcode = new Invocation (new MemberAccess (equality_comparer,
1842                                         "GetHashCode", loc), arguments_hashcode);
1843
1844                                 IntConstant FNV_prime = new IntConstant (16777619, loc);                                
1845                                 rs_hashcode = new Binary (Binary.Operator.Multiply,
1846                                         new Binary (Binary.Operator.ExclusiveOr, rs_hashcode, field_hashcode),
1847                                         FNV_prime);
1848
1849                                 Expression field_to_string = new Conditional (new BooleanExpression (new Binary (Binary.Operator.Inequality,
1850                                         new MemberAccess (new This (f.Location), f.Name), new NullLiteral (loc))),
1851                                         new Invocation (new MemberAccess (
1852                                                 new MemberAccess (new This (f.Location), f.Name), "ToString"), null),
1853                                         new StringConstant (string.Empty, loc));
1854
1855                                 if (rs_equals == null) {
1856                                         rs_equals = field_equal;
1857                                         string_concat = new Binary (Binary.Operator.Addition,
1858                                                 string_concat,
1859                                                 new Binary (Binary.Operator.Addition,
1860                                                         new StringConstant (" " + p.Name + " = ", loc),
1861                                                         field_to_string));
1862                                         continue;
1863                                 }
1864
1865                                 //
1866                                 // Implementation of ToString () body using string concatenation
1867                                 //                              
1868                                 string_concat = new Binary (Binary.Operator.Addition,
1869                                         new Binary (Binary.Operator.Addition,
1870                                                 string_concat,
1871                                                 new StringConstant (", " + p.Name + " = ", loc)),
1872                                         field_to_string);
1873
1874                                 rs_equals = new Binary (Binary.Operator.LogicalAnd, rs_equals, field_equal);
1875                         }
1876
1877                         string_concat = new Binary (Binary.Operator.Addition,
1878                                 string_concat,
1879                                 new StringConstant (" }", loc));
1880
1881                         //
1882                         // Equals (object obj) override
1883                         //              
1884                         LocalVariableReference other_variable_assign = new LocalVariableReference (equals_block, "other", loc);
1885                         equals_block.AddStatement (new StatementExpression (
1886                                 new SimpleAssign (other_variable_assign,
1887                                         new As (equals_block.GetParameterReference ("obj", loc),
1888                                                 current_type, loc), loc)));
1889
1890                         Expression equals_test = new Binary (Binary.Operator.Inequality, other_variable, new NullLiteral (loc));
1891                         if (rs_equals != null)
1892                                 equals_test = new Binary (Binary.Operator.LogicalAnd, equals_test, rs_equals);
1893                         equals_block.AddStatement (new Return (equals_test, loc));
1894
1895                         equals.Block = equals_block;
1896                         equals.Define ();
1897                         AddMethod (equals);
1898
1899                         //
1900                         // GetHashCode () override
1901                         //
1902                         Method hashcode = new Method (this, null, TypeManager.system_int32_expr,
1903                                 Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN,
1904                                 new MemberName ("GetHashCode", loc),
1905                                 Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null);
1906
1907                         //
1908                         // Modified FNV with good avalanche behavior and uniform
1909                         // distribution with larger hash sizes.
1910                         //
1911                         // const int FNV_prime = 16777619;
1912                         // int hash = (int) 2166136261;
1913                         // foreach (int d in data)
1914                         //     hash = (hash ^ d) * FNV_prime;
1915                         // hash += hash << 13;
1916                         // hash ^= hash >> 7;
1917                         // hash += hash << 3;
1918                         // hash ^= hash >> 17;
1919                         // hash += hash << 5;
1920
1921                         ToplevelBlock hashcode_top = new ToplevelBlock (Compiler, loc);
1922                         Block hashcode_block = new Block (hashcode_top);
1923                         hashcode_top.AddStatement (new Unchecked (hashcode_block));
1924
1925                         hashcode_block.AddVariable (TypeManager.system_int32_expr, "hash", loc);
1926                         LocalVariableReference hash_variable = new LocalVariableReference (hashcode_block, "hash", loc);
1927                         LocalVariableReference hash_variable_assign = new LocalVariableReference (hashcode_block, "hash", loc);
1928                         hashcode_block.AddStatement (new StatementExpression (
1929                                 new SimpleAssign (hash_variable_assign, rs_hashcode)));
1930
1931                         hashcode_block.AddStatement (new StatementExpression (
1932                                 new CompoundAssign (Binary.Operator.Addition, hash_variable,
1933                                         new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (13, loc)))));
1934                         hashcode_block.AddStatement (new StatementExpression (
1935                                 new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable,
1936                                         new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (7, loc)))));
1937                         hashcode_block.AddStatement (new StatementExpression (
1938                                 new CompoundAssign (Binary.Operator.Addition, hash_variable,
1939                                         new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (3, loc)))));
1940                         hashcode_block.AddStatement (new StatementExpression (
1941                                 new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable,
1942                                         new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (17, loc)))));
1943                         hashcode_block.AddStatement (new StatementExpression (
1944                                 new CompoundAssign (Binary.Operator.Addition, hash_variable,
1945                                         new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (5, loc)))));
1946
1947                         hashcode_block.AddStatement (new Return (hash_variable, loc));
1948                         hashcode.Block = hashcode_top;
1949                         hashcode.Define ();
1950                         AddMethod (hashcode);
1951
1952                         //
1953                         // ToString () override
1954                         //
1955
1956                         ToplevelBlock tostring_block = new ToplevelBlock (Compiler, loc);
1957                         tostring_block.AddStatement (new Return (string_concat, loc));
1958                         tostring.Block = tostring_block;
1959                         tostring.Define ();
1960                         AddMethod (tostring);
1961
1962                         return true;
1963                 }
1964
1965                 public override string GetSignatureForError ()
1966                 {
1967                         return SignatureForError;
1968                 }
1969
1970                 public IList<AnonymousTypeParameter> Parameters {
1971                         get {
1972                                 return parameters;
1973                         }
1974                 }
1975         }
1976 }