2002-08-29 Rafael Teixeira <rafaelteixeirabr@hotmail.com>
[mono.git] / mcs / mbas / delegate.cs
1 //
2 // delegate.cs: Delegate Handler
3 //
4 // Author: Ravi Pratap (ravi@ximian.com)
5 //
6 // Licensed under the terms of the GNU GPL
7 //
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
9 //
10 //
11
12 using System;
13 using System.Collections;
14 using System.Reflection;
15 using System.Reflection.Emit;
16 using System.Text;
17
18 namespace Mono.CSharp {
19
20         /// <summary>
21         ///   Holds Delegates
22         /// </summary>
23         public class Delegate : DeclSpace {
24                 public Expression ReturnType;
25                 public Parameters      Parameters;
26                 public Attributes      OptAttributes;
27
28                 public ConstructorBuilder ConstructorBuilder;
29                 public MethodBuilder      InvokeBuilder;
30                 public MethodBuilder      BeginInvokeBuilder;
31                 public MethodBuilder      EndInvokeBuilder;
32                 
33                 Type [] param_types;
34                 Type ret_type;
35                 
36                 Expression instance_expr;
37                 MethodBase delegate_method;
38         
39                 const int AllowedModifiers =
40                         Modifiers.NEW |
41                         Modifiers.PUBLIC |
42                         Modifiers.PROTECTED |
43                         Modifiers.INTERNAL |
44                         Modifiers.UNSAFE |
45                         Modifiers.PRIVATE;
46
47                 public Delegate (TypeContainer parent, Expression type, int mod_flags,
48                                  string name, Parameters param_list,
49                                  Attributes attrs, Location l)
50                         : base (parent, name, l)
51                 {
52                         this.ReturnType = type;
53                         ModFlags        = Modifiers.Check (AllowedModifiers, mod_flags,
54                                                            IsTopLevel ? Modifiers.INTERNAL :
55                                                            Modifiers.PRIVATE, l);
56                         Parameters      = param_list;
57                         OptAttributes   = attrs;
58                 }
59
60                 public override TypeBuilder DefineType ()
61                 {
62                         TypeAttributes attr;
63
64                         if (TypeBuilder != null)
65                                 return TypeBuilder;
66                         
67                         if (IsTopLevel) {
68                                 ModuleBuilder builder = CodeGen.ModuleBuilder;
69                                 attr = TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Sealed;
70
71                                 TypeBuilder = builder.DefineType (
72                                         Name, attr, TypeManager.multicast_delegate_type);
73                         } else {
74                                 TypeBuilder builder = Parent.TypeBuilder;
75                                 attr = TypeAttributes.NestedPublic | TypeAttributes.Class |
76                                         TypeAttributes.Sealed;
77
78                                 string name = Name.Substring (1 + Name.LastIndexOf ('.'));
79                                 TypeBuilder = builder.DefineNestedType (
80                                         name, attr, TypeManager.multicast_delegate_type);
81                         }
82
83                         TypeManager.AddDelegateType (Name, TypeBuilder, this);
84
85                         return TypeBuilder;
86                 }
87
88                 public override bool DefineMembers (TypeContainer container)
89                 {
90                         return true;
91                 }
92
93                 public override bool Define (TypeContainer container)
94                 {
95                         MethodAttributes mattr;
96                         int i;
97
98                         // FIXME: POSSIBLY make this static, as it is always constant
99                         //
100                         Type [] const_arg_types = new Type [2];
101                         const_arg_types [0] = TypeManager.object_type;
102                         const_arg_types [1] = TypeManager.intptr_type;
103
104                         mattr = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName |
105                                 MethodAttributes.HideBySig | MethodAttributes.Public;
106
107                         ConstructorBuilder = TypeBuilder.DefineConstructor (mattr,
108                                                                             CallingConventions.Standard,
109                                                                             const_arg_types);
110
111                         ConstructorBuilder.DefineParameter (1, ParameterAttributes.None, "object");
112                         ConstructorBuilder.DefineParameter (2, ParameterAttributes.None, "method");
113                         //
114                         // HACK because System.Reflection.Emit is lame
115                         //
116                         //
117                         // FIXME: POSSIBLY make these static, as they are always the same
118                         Parameter [] fixed_pars = new Parameter [2];
119                         fixed_pars [0] = new Parameter (null, null, Parameter.Modifier.NONE, null);
120                         fixed_pars [1] = new Parameter (null, null, Parameter.Modifier.NONE, null);
121                         Parameters const_parameters = new Parameters (fixed_pars, null, Location);
122                         
123                         TypeManager.RegisterMethod (
124                                 ConstructorBuilder,
125                                 new InternalParameters (const_arg_types, const_parameters),
126                                 const_arg_types);
127                                 
128                         
129                         ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
130
131                         //
132                         // Here the various methods like Invoke, BeginInvoke etc are defined
133                         //
134                         // First, call the `out of band' special method for
135                         // defining recursively any types we need:
136                         
137                         if (!Parameters.ComputeAndDefineParameterTypes (this))
138                                 return false;
139                         
140                         param_types = Parameters.GetParameterInfo (this);
141                         if (param_types == null)
142                                 return false;
143
144                         //
145                         // Invoke method
146                         //
147
148                         // Check accessibility
149                         foreach (Type partype in param_types)
150                                 if (!container.AsAccessible (partype, ModFlags)) {
151                                         Report.Error (59, Location,
152                                                       "Inconsistent accessibility: parameter type `" +
153                                                       TypeManager.CSharpName (partype) + "` is less " +
154                                                       "accessible than delegate `" + Name + "'");
155                                         return false;
156                                 }
157                         
158                         ReturnType = ResolveTypeExpr (ReturnType, false, Location);
159                         ret_type = ReturnType.Type;
160                         if (ret_type == null)
161                                 return false;
162
163                         if (!container.AsAccessible (ret_type, ModFlags)) {
164                                 Report.Error (58, Location,
165                                               "Inconsistent accessibility: return type `" +
166                                               TypeManager.CSharpName (ret_type) + "` is less " +
167                                               "accessible than delegate `" + Name + "'");
168                                 return false;
169                         }
170
171                         //
172                         // We don't have to check any others because they are all
173                         // guaranteed to be accessible - they are standard types.
174                         //
175                         
176                         CallingConventions cc = Parameters.GetCallingConvention ();
177
178                         mattr = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual;
179
180                         InvokeBuilder = TypeBuilder.DefineMethod ("Invoke", 
181                                                                   mattr,                     
182                                                                   cc,
183                                                                   ret_type,                  
184                                                                   param_types);
185
186                         i = 0;
187                         if (Parameters.FixedParameters != null){
188                                 int top = Parameters.FixedParameters.Length;
189                                 Parameter p;
190                                 
191                                 for (; i < top; i++) {
192                                         p = Parameters.FixedParameters [i];
193
194                                         InvokeBuilder.DefineParameter (
195                                                 i+1, p.Attributes, p.Name);
196                                 }
197                         }
198                         if (Parameters.ArrayParameter != null){
199                                 Parameter p = Parameters.ArrayParameter;
200                                 
201                                 InvokeBuilder.DefineParameter (
202                                         i+1, p.Attributes, p.Name);
203                         }
204                         
205                         InvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
206
207                         TypeManager.RegisterMethod (InvokeBuilder,
208                                                     new InternalParameters (container, Parameters),
209                                                     param_types);
210
211                         //
212                         // BeginInvoke
213                         //
214                         int params_num = param_types.Length;
215                         Type [] async_param_types = new Type [params_num + 2];
216
217                         param_types.CopyTo (async_param_types, 0);
218
219                         async_param_types [params_num] = TypeManager.asynccallback_type;
220                         async_param_types [params_num + 1] = TypeManager.object_type;
221
222                         mattr = MethodAttributes.Public | MethodAttributes.HideBySig |
223                                 MethodAttributes.Virtual | MethodAttributes.NewSlot;
224                         
225                         BeginInvokeBuilder = TypeBuilder.DefineMethod ("BeginInvoke",
226                                                                        mattr,
227                                                                        cc,
228                                                                        TypeManager.iasyncresult_type,
229                                                                        async_param_types);
230
231                         i = 0;
232                         if (Parameters.FixedParameters != null){
233                                 int top = Parameters.FixedParameters.Length;
234                                 Parameter p;
235                                 
236                                 for (i = 0 ; i < top; i++) {
237                                         p = Parameters.FixedParameters [i];
238
239                                         BeginInvokeBuilder.DefineParameter (
240                                                 i+1, p.Attributes, p.Name);
241                                 }
242                         }
243                         if (Parameters.ArrayParameter != null){
244                                 Parameter p = Parameters.ArrayParameter;
245                                 
246                                 BeginInvokeBuilder.DefineParameter (
247                                         i+1, p.Attributes, p.Name);
248                                 i++;
249                         }
250
251                         BeginInvokeBuilder.DefineParameter (i + 1, ParameterAttributes.None, "callback");
252                         BeginInvokeBuilder.DefineParameter (i + 2, ParameterAttributes.None, "object");
253                         
254                         BeginInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
255
256                         Parameter [] async_params = new Parameter [params_num + 2];
257                         int n = 0;
258                         if (Parameters.FixedParameters != null){
259                                 Parameters.FixedParameters.CopyTo (async_params, 0);
260                                 n = Parameters.FixedParameters.Length;
261                         }
262                         if (Parameters.ArrayParameter != null)
263                                 async_params [n] = Parameters.ArrayParameter;
264                         
265                         async_params [params_num] = new Parameter (
266                                 TypeManager.system_asynccallback_expr, "callback",
267                                                                    Parameter.Modifier.NONE, null);
268                         async_params [params_num + 1] = new Parameter (
269                                 TypeManager.system_object_expr, "object",
270                                                                    Parameter.Modifier.NONE, null);
271
272                         Parameters async_parameters = new Parameters (async_params, null, Location);
273                         
274                         async_parameters.ComputeAndDefineParameterTypes (this);
275                         TypeManager.RegisterMethod (BeginInvokeBuilder,
276                                                     new InternalParameters (container, async_parameters),
277                                                     async_param_types);
278
279                         //
280                         // EndInvoke
281                         //
282                         Type [] end_param_types = new Type [1];
283                         end_param_types [0] = TypeManager.iasyncresult_type;
284                         
285                         EndInvokeBuilder = TypeBuilder.DefineMethod ("EndInvoke",
286                                                                      mattr,
287                                                                      cc,
288                                                                      ret_type,
289                                                                      end_param_types);
290                         EndInvokeBuilder.DefineParameter (1, ParameterAttributes.None, "result");
291                         
292                         EndInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
293
294                         Parameter [] end_params = new Parameter [1];
295                         end_params [0] = new Parameter (
296                                 TypeManager.system_iasyncresult_expr, "result",
297                                                         Parameter.Modifier.NONE, null);
298
299                         TypeManager.RegisterMethod (
300                                 EndInvokeBuilder, new InternalParameters (
301                                         container,
302                                         new Parameters (
303                                                 end_params, null, Location)),
304                                                     end_param_types);
305
306                         return true;
307                 }
308
309                 /// <summary>
310                 ///  Verifies whether the method in question is compatible with the delegate
311                 ///  Returns the method itself if okay and null if not.
312                 /// </summary>
313                 public static MethodBase VerifyMethod (EmitContext ec, Type delegate_type, MethodBase mb,
314                                                        Location loc)
315                 {
316                         ParameterData pd = Invocation.GetParameterData (mb);
317
318                         int pd_count = pd.Count;
319
320                         Expression ml = Expression.MemberLookup (
321                                 ec, delegate_type, "Invoke", loc);
322
323                         if (!(ml is MethodGroupExpr)) {
324                                 Report.Error (-100, loc, "Internal error : could not find Invoke method!");
325                                 return null;
326                         }
327
328                         MethodBase invoke_mb = ((MethodGroupExpr) ml).Methods [0];
329
330                         ParameterData invoke_pd = Invocation.GetParameterData (invoke_mb);
331
332                         if (invoke_pd.Count != pd_count)
333                                 return null;
334
335                         for (int i = pd_count; i > 0; ) {
336                                 i--;
337
338                                 if (invoke_pd.ParameterType (i) == pd.ParameterType (i))
339                                         continue;
340                                 else
341                                         return null;
342                         }
343
344                         if (((MethodInfo) invoke_mb).ReturnType == ((MethodInfo) mb).ReturnType)
345                                 return mb;
346                         else
347                                 return null;
348                 }
349
350                 // <summary>
351                 //  Verifies whether the invocation arguments are compatible with the
352                 //  delegate's target method
353                 // </summary>
354                 public static bool VerifyApplicability (EmitContext ec,
355                                                         Type delegate_type,
356                                                         ArrayList args,
357                                                         Location loc)
358                 {
359                         int arg_count;
360
361                         if (args == null)
362                                 arg_count = 0;
363                         else
364                                 arg_count = args.Count;
365
366                         Expression ml = Expression.MemberLookup (
367                                 ec, delegate_type, "Invoke", loc);
368                         
369                         if (!(ml is MethodGroupExpr)) {
370                                 Report.Error (-100, loc, "Internal error : could not find Invoke method!");
371                                 return false;
372                         }
373                         
374                         MethodBase mb = ((MethodGroupExpr) ml).Methods [0];
375                         ParameterData pd = Invocation.GetParameterData (mb);
376
377                         int pd_count = pd.Count;
378
379                         bool not_params_method = (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS);
380
381                         if (not_params_method && pd_count != arg_count) {
382                                 Report.Error (1593, loc,
383                                               "Delegate '" + delegate_type.ToString ()
384                                               + "' does not take '" + arg_count + "' arguments");
385                                 return false;
386                         }
387
388                         return Invocation.VerifyArgumentsCompat (ec, args, arg_count, mb, !not_params_method,
389                                                                  delegate_type, loc);
390                 }
391                 
392                 /// <summary>
393                 ///  Verifies whether the delegate in question is compatible with this one in
394                 ///  order to determine if instantiation from the same is possible.
395                 /// </summary>
396                 public static bool VerifyDelegate (EmitContext ec, Type delegate_type, Type probe_type, Location loc)
397                 {
398                         Expression ml = Expression.MemberLookup (
399                                 ec, delegate_type, "Invoke", loc);
400                         
401                         if (!(ml is MethodGroupExpr)) {
402                                 Report.Error (-100, loc, "Internal error : could not find Invoke method!");
403                                 return false;
404                         }
405                         
406                         MethodBase mb = ((MethodGroupExpr) ml).Methods [0];
407                         ParameterData pd = Invocation.GetParameterData (mb);
408
409                         Expression probe_ml = Expression.MemberLookup (
410                                 ec, delegate_type, "Invoke", loc);
411                         
412                         if (!(probe_ml is MethodGroupExpr)) {
413                                 Report.Error (-100, loc, "Internal error : could not find Invoke method!");
414                                 return false;
415                         }
416                         
417                         MethodBase probe_mb = ((MethodGroupExpr) probe_ml).Methods [0];
418                         ParameterData probe_pd = Invocation.GetParameterData (probe_mb);
419                         
420                         if (((MethodInfo) mb).ReturnType != ((MethodInfo) probe_mb).ReturnType)
421                                 return false;
422
423                         if (pd.Count != probe_pd.Count)
424                                 return false;
425
426                         for (int i = pd.Count; i > 0; ) {
427                                 i--;
428
429                                 if (pd.ParameterType (i) != probe_pd.ParameterType (i) ||
430                                     pd.ParameterModifier (i) != probe_pd.ParameterModifier (i))
431                                         return false;
432                         }
433                         
434                         return true;
435                 }
436                 
437                 public static string FullDelegateDesc (Type del_type, MethodBase mb, ParameterData pd)
438                 {
439                         StringBuilder sb = new StringBuilder (TypeManager.CSharpName (((MethodInfo) mb).ReturnType));
440                         
441                         sb.Append (" " + del_type.ToString ());
442                         sb.Append (" (");
443
444                         int length = pd.Count;
445                         
446                         for (int i = length; i > 0; ) {
447                                 i--;
448                                 
449                                 sb.Append (TypeManager.CSharpName (pd.ParameterType (length - i - 1)));
450                                 if (i != 0)
451                                         sb.Append (", ");
452                         }
453                         
454                         sb.Append (")");
455                         return sb.ToString ();
456                         
457                 }
458                 
459                 // Hack around System.Reflection as found everywhere else
460                 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
461                                                         MemberFilter filter, object criteria)
462                 {
463                         ArrayList members = new ArrayList ();
464
465                         if ((mt & MemberTypes.Method) != 0) {
466                                 if (ConstructorBuilder != null)
467                                 if (filter (ConstructorBuilder, criteria))
468                                         members.Add (ConstructorBuilder);
469
470                                 if (InvokeBuilder != null)
471                                 if (filter (InvokeBuilder, criteria))
472                                         members.Add (InvokeBuilder);
473
474                                 if (BeginInvokeBuilder != null)
475                                 if (filter (BeginInvokeBuilder, criteria))
476                                         members.Add (BeginInvokeBuilder);
477
478                                 if (EndInvokeBuilder != null)
479                                 if (filter (EndInvokeBuilder, criteria))
480                                         members.Add (EndInvokeBuilder);
481                         }
482
483                         return new MemberList (members);
484                 }
485
486                 public override MemberCache MemberCache {
487                         get {
488                                 return null;
489                         }
490                 }
491
492                 public void CloseDelegate ()
493                 {
494                         TypeBuilder.CreateType ();
495                 }
496                 
497                 public Expression InstanceExpression {
498                         get {
499                                 return instance_expr;
500                         }
501                         set {
502                                 instance_expr = value;
503                         }
504                 }
505
506                 public MethodBase TargetMethod {
507                         get {
508                                 return delegate_method;
509                         }
510                         set {
511                                 delegate_method = value;
512                         }
513                 }
514
515                 public Type TargetReturnType {
516                         get {
517                                 return ret_type;
518                         }
519                 }
520
521                 public Type [] ParameterTypes {
522                         get {
523                                 return param_types;
524                         }
525                 }
526                 
527         }
528
529         public class NewDelegate : Expression {
530
531                 public ArrayList Arguments;
532
533                 MethodBase constructor_method;
534                 MethodBase delegate_method;
535                 Expression delegate_instance_expr;
536
537                 public NewDelegate (Type type, ArrayList Arguments, Location loc)
538                 {
539                         this.type = type;
540                         this.Arguments = Arguments;
541                         this.loc  = loc; 
542                 }
543
544                 public override Expression DoResolve (EmitContext ec)
545                 {
546                         if (Arguments == null) {
547                                 Report.Error (-11, loc,
548                                               "Delegate creation expression takes only one argument");
549                                 return null;
550                         }
551
552                         if (Arguments.Count != 1) {
553                                 Report.Error (-11, loc,
554                                               "Delegate creation expression takes only one argument");
555                                 return null;
556                         }
557
558                         Expression ml = Expression.MemberLookup (
559                                 ec, type, ".ctor", loc);
560
561                         if (!(ml is MethodGroupExpr)) {
562                                 Report.Error (-100, loc, "Internal error : Could not find delegate constructor!");
563                                 return null;
564                         }
565
566                         constructor_method = ((MethodGroupExpr) ml).Methods [0];
567                         Argument a = (Argument) Arguments [0];
568                         
569                         if (!a.ResolveMethodGroup (ec, Location))
570                                 return null;
571                         
572                         Expression e = a.Expr;
573
574                         Expression invoke_method = Expression.MemberLookup (
575                                 ec, type, "Invoke", MemberTypes.Method,
576                                 Expression.AllBindingFlags, loc);
577
578                         if (invoke_method == null) {
579                                 Report.Error (-200, loc, "Internal error ! COuld not find Invoke method!");
580                                 return null;
581                         }
582
583                         if (e is MethodGroupExpr) {
584                                 MethodGroupExpr mg = (MethodGroupExpr) e;
585
586                                 foreach (MethodInfo mi in mg.Methods){
587                                         delegate_method  = Delegate.VerifyMethod (ec, type, mi, loc);
588
589                                         if (delegate_method != null)
590                                                 break;
591                                 }
592                                         
593                                 if (delegate_method == null) {
594                                         string method_desc;
595                                         if (mg.Methods.Length > 1)
596                                                 method_desc = mg.Methods [0].Name;
597                                         else
598                                                 method_desc = Invocation.FullMethodDesc (mg.Methods [0]);
599
600                                         MethodBase dm = ((MethodGroupExpr) invoke_method).Methods [0];
601                                         ParameterData param = Invocation.GetParameterData (dm);
602                                         string delegate_desc = Delegate.FullDelegateDesc (type, dm, param);
603
604                                         Report.Error (123, loc, "Method '" + method_desc + "' does not " +
605                                                       "match delegate '" + delegate_desc + "'");
606
607                                         return null;
608                                 }
609                                                 
610                                 if (mg.InstanceExpression != null)
611                                         delegate_instance_expr = mg.InstanceExpression.Resolve (ec);
612                                 else {
613                                         if (!ec.IsStatic)
614                                                 delegate_instance_expr = ec.This;
615                                         else
616                                                 delegate_instance_expr = null;
617                                 }
618
619                                 if (delegate_instance_expr != null)
620                                         if (delegate_instance_expr.Type.IsValueType)
621                                                 delegate_instance_expr = new BoxedCast (delegate_instance_expr);
622                                 
623                                 eclass = ExprClass.Value;
624                                 return this;
625                         }
626
627                         Type e_type = e.Type;
628
629                         if (!TypeManager.IsDelegateType (e_type)) {
630                                 Report.Error (-12, loc, "Cannot create a delegate from something " +
631                                               "not a delegate or a method.");
632                                 return null;
633                         }
634
635                         // This is what MS' compiler reports. We could always choose
636                         // to be more verbose and actually give delegate-level specifics
637                         
638                         if (!Delegate.VerifyDelegate (ec, type, e_type, loc)) {
639                                 Report.Error (29, loc, "Cannot implicitly convert type '" + e_type + "' " +
640                                               "to type '" + type + "'");
641                                 return null;
642                         }
643                                 
644                         delegate_instance_expr = e;
645                         delegate_method        = ((MethodGroupExpr) invoke_method).Methods [0];
646                         
647                         eclass = ExprClass.Value;
648                         return this;
649                 }
650                 
651                 public override void Emit (EmitContext ec)
652                 {
653                         if (delegate_instance_expr == null ||
654                             delegate_method.IsStatic)
655                                 ec.ig.Emit (OpCodes.Ldnull);
656                         else
657                                 delegate_instance_expr.Emit (ec);
658                         
659                         ec.ig.Emit (OpCodes.Ldftn, (MethodInfo) delegate_method);
660                         ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) constructor_method);
661                 }
662         }
663
664         public class DelegateInvocation : ExpressionStatement {
665
666                 public Expression InstanceExpr;
667                 public ArrayList  Arguments;
668
669                 MethodBase method;
670                 
671                 public DelegateInvocation (Expression instance_expr, ArrayList args, Location loc)
672                 {
673                         this.InstanceExpr = instance_expr;
674                         this.Arguments = args;
675                         this.loc = loc;
676                 }
677
678                 public override Expression DoResolve (EmitContext ec)
679                 {
680                         if (InstanceExpr is EventExpr) {
681                                 
682                                 EventInfo ei = ((EventExpr) InstanceExpr).EventInfo;
683                                 
684                                 Expression ml = MemberLookup (
685                                         ec, ec.ContainerType, ei.Name,
686                                         MemberTypes.Event, AllBindingFlags | BindingFlags.DeclaredOnly, loc);
687
688                                 if (ml == null) {
689                                         //
690                                         // If this is the case, then the Event does not belong 
691                                         // to this Type and so, according to the spec
692                                         // cannot be accessed directly
693                                         //
694                                         // Note that target will not appear as an EventExpr
695                                         // in the case it is being referenced within the same type container;
696                                         // it will appear as a FieldExpr in that case.
697                                         //
698                                         
699                                         Assign.error70 (ei, loc);
700                                         return null;
701                                 }
702                         }
703                         
704                         
705                         Type del_type = InstanceExpr.Type;
706                         if (del_type == null)
707                                 return null;
708                         
709                         if (Arguments != null){
710                                 foreach (Argument a in Arguments){
711                                         if (!a.Resolve (ec, loc))
712                                                 return null;
713                                 }
714                         }
715                         
716                         if (!Delegate.VerifyApplicability (ec, del_type, Arguments, loc))
717                                 return null;
718
719                         Expression lookup = Expression.MemberLookup (ec, del_type, "Invoke", loc);
720                         if (!(lookup is MethodGroupExpr)) {
721                                 Report.Error (-100, loc, "Internal error : could not find Invoke method!");
722                                 return null;
723                         }
724                         
725                         method = ((MethodGroupExpr) lookup).Methods [0];
726                         type = ((MethodInfo) method).ReturnType;
727                         eclass = ExprClass.Value;
728                         
729                         return this;
730                 }
731
732                 public override void Emit (EmitContext ec)
733                 {
734                         Delegate del = TypeManager.LookupDelegate (InstanceExpr.Type);
735
736                         //
737                         // Invocation on delegates call the virtual Invoke member
738                         // so we are always `instance' calls
739                         //
740                         Invocation.EmitCall (ec, false, false, InstanceExpr, method, Arguments, loc);
741                 }
742
743                 public override void EmitStatement (EmitContext ec)
744                 {
745                         Emit (ec);
746                         // 
747                         // Pop the return value if there is one
748                         //
749                         if (method is MethodInfo){
750                                 if (((MethodInfo) method).ReturnType != TypeManager.void_type)
751                                         ec.ig.Emit (OpCodes.Pop);
752                         }
753                 }
754
755         }
756 }