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