2004-02-07 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.MonoBASIC {
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.MonoBASIC_Name (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.MonoBASIC_Name (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!" + delegate_type);
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_count == 0) ||
380                                 (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS);
381
382                         if (not_params_method && pd_count != arg_count) {
383                                 Report.Error (1593, loc,
384                                               "Delegate '" + delegate_type.ToString ()
385                                               + "' does not take '" + arg_count + "' arguments");
386                                 return false;
387                         }
388
389                         return Invocation.VerifyArgumentsCompat (ec, args, arg_count, mb, !not_params_method,
390                                                                  delegate_type, loc);
391                 }
392                 
393                 /// <summary>
394                 ///  Verifies whether the delegate in question is compatible with this one in
395                 ///  order to determine if instantiation from the same is possible.
396                 /// </summary>
397                 public static bool VerifyDelegate (EmitContext ec, Type delegate_type, Type probe_type, Location loc)
398                 {
399                         Expression ml = Expression.MemberLookup (
400                                 ec, delegate_type, "Invoke", loc);
401                         
402                         if (!(ml is MethodGroupExpr)) {
403                                 Report.Error (-100, loc, "Internal error: could not find Invoke method!");
404                                 return false;
405                         }
406                         
407                         MethodBase mb = ((MethodGroupExpr) ml).Methods [0];
408                         ParameterData pd = Invocation.GetParameterData (mb);
409
410                         Expression probe_ml = Expression.MemberLookup (
411                                 ec, delegate_type, "Invoke", loc);
412                         
413                         if (!(probe_ml is MethodGroupExpr)) {
414                                 Report.Error (-100, loc, "Internal error: could not find Invoke method!");
415                                 return false;
416                         }
417                         
418                         MethodBase probe_mb = ((MethodGroupExpr) probe_ml).Methods [0];
419                         ParameterData probe_pd = Invocation.GetParameterData (probe_mb);
420                         
421                         if (((MethodInfo) mb).ReturnType != ((MethodInfo) probe_mb).ReturnType)
422                                 return false;
423
424                         if (pd.Count != probe_pd.Count)
425                                 return false;
426
427                         for (int i = pd.Count; i > 0; ) {
428                                 i--;
429
430                                 if (pd.ParameterType (i) != probe_pd.ParameterType (i) ||
431                                     pd.ParameterModifier (i) != probe_pd.ParameterModifier (i))
432                                         return false;
433                         }
434                         
435                         return true;
436                 }
437                 
438                 public static string FullDelegateDesc (Type del_type, MethodBase mb, ParameterData pd)
439                 {
440                         StringBuilder sb = new StringBuilder (TypeManager.MonoBASIC_Name (((MethodInfo) mb).ReturnType));
441                         
442                         sb.Append (" " + del_type.ToString ());
443                         sb.Append (" (");
444
445                         int length = pd.Count;
446                         
447                         for (int i = length; i > 0; ) {
448                                 i--;
449                                 
450                                 sb.Append (TypeManager.MonoBASIC_Name (pd.ParameterType (length - i - 1)));
451                                 if (i != 0)
452                                         sb.Append (", ");
453                         }
454                         
455                         sb.Append (")");
456                         return sb.ToString ();
457                         
458                 }
459                 
460                 // Hack around System.Reflection as found everywhere else
461                 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
462                                                         MemberFilter filter, object criteria)
463                 {
464                         ArrayList members = new ArrayList ();
465
466                         if ((mt & MemberTypes.Method) != 0) {
467                                 if (ConstructorBuilder != null)
468                                 if (filter (ConstructorBuilder, criteria))
469                                         members.Add (ConstructorBuilder);
470
471                                 if (InvokeBuilder != null)
472                                 if (filter (InvokeBuilder, criteria))
473                                         members.Add (InvokeBuilder);
474
475                                 if (BeginInvokeBuilder != null)
476                                 if (filter (BeginInvokeBuilder, criteria))
477                                         members.Add (BeginInvokeBuilder);
478
479                                 if (EndInvokeBuilder != null)
480                                 if (filter (EndInvokeBuilder, criteria))
481                                         members.Add (EndInvokeBuilder);
482                         }
483
484                         return new MemberList (members);
485                 }
486
487                 public override MemberCache MemberCache {
488                         get {
489                                 return null;
490                         }
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.ResolveMethodGroup (ec, Location))
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                                 //
607                                 // Check safe/unsafe of the delegate
608                                 //
609                                 if (!ec.InUnsafe){
610                                         ParameterData param = Invocation.GetParameterData (delegate_method);
611                                         int count = param.Count;
612                                         
613                                         for (int i = 0; i < count; i++){
614                                                 if (param.ParameterType (i).IsPointer){
615                                                         Expression.UnsafeError (loc);
616                                                         return null;
617                                                 }
618                                         }
619                                 }
620                                                 
621                                 if (mg.InstanceExpression != null)
622                                         delegate_instance_expr = mg.InstanceExpression.Resolve (ec);
623                                 else {
624                                         if (!ec.IsStatic)
625                                                 delegate_instance_expr = ec.This;
626                                         else
627                                                 delegate_instance_expr = null;
628                                 }
629
630                                 if (delegate_instance_expr != null)
631                                         if (delegate_instance_expr.Type.IsValueType)
632                                                 delegate_instance_expr = new BoxedCast (delegate_instance_expr);
633                                 
634                                 eclass = ExprClass.Value;
635                                 return this;
636                         }
637
638                         Type e_type = e.Type;
639
640                         if (!TypeManager.IsDelegateType (e_type)) {
641                                 Report.Error (-12, loc, "Cannot create a delegate from something " +
642                                               "not a delegate or a method.");
643                                 return null;
644                         }
645
646                         // This is what MS' compiler reports. We could always choose
647                         // to be more verbose and actually give delegate-level specifics
648                         
649                         if (!Delegate.VerifyDelegate (ec, type, e_type, loc)) {
650                                 Report.Error (29, loc, "Cannot implicitly convert type '" + e_type + "' " +
651                                               "to type '" + type + "'");
652                                 return null;
653                         }
654                                 
655                         delegate_instance_expr = e;
656                         delegate_method = ((MethodGroupExpr) invoke_method).Methods [0];
657                         
658                         eclass = ExprClass.Value;
659                         return this;
660                 }
661                 
662                 public override void Emit (EmitContext ec)
663                 {
664                         if (delegate_instance_expr == null ||
665                             delegate_method.IsStatic)
666                                 ec.ig.Emit (OpCodes.Ldnull);
667                         else
668                                 delegate_instance_expr.Emit (ec);
669                         
670                         if (delegate_method.IsVirtual) {
671                                 ec.ig.Emit (OpCodes.Dup);
672                                 ec.ig.Emit (OpCodes.Ldvirtftn, (MethodInfo) delegate_method);
673                         } else
674                                 ec.ig.Emit (OpCodes.Ldftn, (MethodInfo) delegate_method);
675                         ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) constructor_method);
676                 }
677         }
678
679         public class DelegateInvocation : ExpressionStatement {
680
681                 public Expression InstanceExpr;
682                 public ArrayList  Arguments;
683
684                 MethodBase method;
685                 
686                 public DelegateInvocation (Expression instance_expr, ArrayList args, Location loc)
687                 {
688                         this.InstanceExpr = instance_expr;
689                         this.Arguments = args;
690                         this.loc = loc;
691                 }
692
693                 public override Expression DoResolve (EmitContext ec)
694                 {
695                         if (InstanceExpr is EventExpr) {
696                                 
697                                 EventInfo ei = ((EventExpr) InstanceExpr).EventInfo;
698                                 
699                                 Expression ml = MemberLookup (
700                                         ec, ec.ContainerType, ei.Name,
701                                         MemberTypes.Event, AllBindingFlags | BindingFlags.DeclaredOnly, loc);
702
703                                 if (ml == null) {
704                                         //
705                                         // If this is the case, then the Event does not belong 
706                                         // to this Type and so, according to the spec
707                                         // cannot be accessed directly
708                                         //
709                                         // Note that target will not appear as an EventExpr
710                                         // in the case it is being referenced within the same type container;
711                                         // it will appear as a FieldExpr in that case.
712                                         //
713                                         
714                                         Assign.error70 (ei, loc);
715                                         return null;
716                                 }
717                         }
718                         
719                         
720                         Type del_type = InstanceExpr.Type;
721                         if (del_type == null)
722                                 return null;
723                         
724                         if (Arguments != null){
725                                 foreach (Argument a in Arguments){
726                                         if (!a.Resolve (ec, loc))
727                                                 return null;
728                                 }
729                         }
730                         
731                         if (!Delegate.VerifyApplicability (ec, del_type, Arguments, loc))
732                                 return null;
733
734                         Expression lookup = Expression.MemberLookup (ec, del_type, "Invoke", loc);
735                         if (!(lookup is MethodGroupExpr)) {
736                                 Report.Error (-100, loc, "Internal error: could not find Invoke method!");
737                                 return null;
738                         }
739                         
740                         method = ((MethodGroupExpr) lookup).Methods [0];
741                         type = ((MethodInfo) method).ReturnType;
742                         eclass = ExprClass.Value;
743                         
744                         return this;
745                 }
746
747                 public override void Emit (EmitContext ec)
748                 {
749                         Delegate del = TypeManager.LookupDelegate (InstanceExpr.Type);
750
751                         //
752                         // Invocation on delegates call the virtual Invoke member
753                         // so we are always `instance' calls
754                         //
755                         Invocation.EmitCall (ec, false, false, InstanceExpr, method, Arguments, loc);
756                 }
757
758                 public override void EmitStatement (EmitContext ec)
759                 {
760                         Emit (ec);
761                         // 
762                         // Pop the return value if there is one
763                         //
764                         if (method is MethodInfo){
765                                 if (((MethodInfo) method).ReturnType != TypeManager.void_type)
766                                         ec.ig.Emit (OpCodes.Pop);
767                         }
768                 }
769
770         }
771 }