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