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