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