2005-02-02 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / mcs / delegate.cs
index bfd128268da794e7340a6e17ab1754eef8c3289b..75a0989906ecb32bf4cbb46ae613d1e2cf3faea2 100644 (file)
-//\r
-// delegate.cs: Delegate Handler\r
-//\r
-// Authors:\r
-//     Ravi Pratap (ravi@ximian.com)\r
-//     Miguel de Icaza (miguel@ximian.com)\r
-//\r
-// Licensed under the terms of the GNU GPL\r
-//\r
-// (C) 2001 Ximian, Inc (http://www.ximian.com)\r
-//\r
-//\r
-\r
-using System;\r
-using System.Collections;\r
-using System.Reflection;\r
-using System.Reflection.Emit;\r
-using System.Text;\r
-\r
-namespace Mono.CSharp {\r
-\r
-       /// <summary>\r
-       ///   Holds Delegates\r
-       /// </summary>\r
-       public class Delegate : DeclSpace {\r
-               public Expression ReturnType;\r
-               public Parameters      Parameters;\r
-
-               public ConstructorBuilder ConstructorBuilder;\r
-               public MethodBuilder      InvokeBuilder;\r
-               public MethodBuilder      BeginInvokeBuilder;\r
-               public MethodBuilder      EndInvokeBuilder;\r
-               \r
-               Type [] param_types;\r
-               Type ret_type;\r
-               \r
-               Expression instance_expr;\r
-               MethodBase delegate_method;\r
-       \r
-               const int AllowedModifiers =\r
-                       Modifiers.NEW |\r
-                       Modifiers.PUBLIC |\r
-                       Modifiers.PROTECTED |\r
-                       Modifiers.INTERNAL |\r
-                       Modifiers.UNSAFE |\r
-                       Modifiers.PRIVATE;\r
-\r
-               public Delegate (NamespaceEntry ns, TypeContainer parent, Expression type,\r
-                                int mod_flags, string name, Parameters param_list,\r
-                                Attributes attrs, Location l)\r
+//
+// delegate.cs: Delegate Handler
+//
+// Authors:
+//     Ravi Pratap (ravi@ximian.com)
+//     Miguel de Icaza (miguel@ximian.com)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001 Ximian, Inc (http://www.ximian.com)
+//
+//
+
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Text;
+
+namespace Mono.CSharp {
+
+       /// <summary>
+       ///   Holds Delegates
+       /// </summary>
+       public class Delegate : DeclSpace {
+               public Expression ReturnType;
+               public Parameters      Parameters;
+
+               public ConstructorBuilder ConstructorBuilder;
+               public MethodBuilder      InvokeBuilder;
+               public MethodBuilder      BeginInvokeBuilder;
+               public MethodBuilder      EndInvokeBuilder;
+               
+               Type [] param_types;
+               Type ret_type;
+
+               static string[] attribute_targets = new string [] { "type", "return" };
+               
+               Expression instance_expr;
+               MethodBase delegate_method;
+               ReturnParameter return_attributes;
+       
+               const int AllowedModifiers =
+                       Modifiers.NEW |
+                       Modifiers.PUBLIC |
+                       Modifiers.PROTECTED |
+                       Modifiers.INTERNAL |
+                       Modifiers.UNSAFE |
+                       Modifiers.PRIVATE;
+
+               public Delegate (NamespaceEntry ns, TypeContainer parent, Expression type,
+                                int mod_flags, MemberName name, Parameters param_list,
+                                Attributes attrs, Location l)
                        : base (ns, parent, name, attrs, l)
 
-               {\r
-                       this.ReturnType = type;\r
-                       ModFlags        = Modifiers.Check (AllowedModifiers, mod_flags,\r
-                                                          IsTopLevel ? Modifiers.INTERNAL :\r
-                                                          Modifiers.PRIVATE, l);\r
-                       Parameters      = param_list;\r          }\r
-\r
-               public override TypeBuilder DefineType ()\r
-               {\r
-                       if (TypeBuilder != null)\r
-                               return TypeBuilder;\r
-\r
-                       TypeAttributes attr = Modifiers.TypeAttr (ModFlags, IsTopLevel) |\r
-                               TypeAttributes.Class | TypeAttributes.Sealed;\r
-\r
-                       if (IsTopLevel) {\r
-                               if (TypeManager.NamespaceClash (Name, Location))\r
-                                       return null;\r
-                               \r
-                               ModuleBuilder builder = CodeGen.ModuleBuilder;\r
-\r
-                               TypeBuilder = builder.DefineType (\r
-                                       Name, attr, TypeManager.multicast_delegate_type);\r
-                       } else {\r
-                               TypeBuilder builder = Parent.TypeBuilder;\r
-\r
-                               string name = Name.Substring (1 + Name.LastIndexOf ('.'));\r
-                               TypeBuilder = builder.DefineNestedType (\r
-                                       name, attr, TypeManager.multicast_delegate_type);\r
-                       }\r
-\r
-                       TypeManager.AddDelegateType (Name, TypeBuilder, this);\r
-\r
-                       return TypeBuilder;\r
-               }\r
-\r
-               public override bool DefineMembers (TypeContainer container)\r
-               {\r
-                       return true;\r
-               }\r
-\r
-               public override bool Define (TypeContainer container)\r
-               {\r
-                       MethodAttributes mattr;\r
-                       int i;\r
-                       ParameterBuilder pb;\r
-                       Attributes cattr;\r
-                       EmitContext ec = new EmitContext (this, this, Location, null,\r
-                                                         null, ModFlags, false);\r
-\r
-                       // FIXME: POSSIBLY make this static, as it is always constant\r
-                       //\r
-                       Type [] const_arg_types = new Type [2];\r
-                       const_arg_types [0] = TypeManager.object_type;\r
-                       const_arg_types [1] = TypeManager.intptr_type;\r
-\r
-                       mattr = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName |\r
-                               MethodAttributes.HideBySig | MethodAttributes.Public;\r
-\r
-                       ConstructorBuilder = TypeBuilder.DefineConstructor (mattr,\r
-                                                                           CallingConventions.Standard,\r
-                                                                           const_arg_types);\r
-\r
-                       ConstructorBuilder.DefineParameter (1, ParameterAttributes.None, "object");\r
-                       ConstructorBuilder.DefineParameter (2, ParameterAttributes.None, "method");\r
-                       //\r
-                       // HACK because System.Reflection.Emit is lame\r
-                       //\r
-                       //\r
-                       // FIXME: POSSIBLY make these static, as they are always the same\r
-                       Parameter [] fixed_pars = new Parameter [2];\r
-                       fixed_pars [0] = new Parameter (null, null, Parameter.Modifier.NONE, null);\r
-                       fixed_pars [1] = new Parameter (null, null, Parameter.Modifier.NONE, null);\r
-                       Parameters const_parameters = new Parameters (fixed_pars, null, Location);\r
-                       \r
-                       TypeManager.RegisterMethod (\r
-                               ConstructorBuilder,\r
-                               new InternalParameters (const_arg_types, const_parameters),\r
-                               const_arg_types);\r
-                               \r
-                       \r
-                       ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);\r
-\r
-                       //\r
-                       // Here the various methods like Invoke, BeginInvoke etc are defined\r
-                       //\r
-                       // First, call the `out of band' special method for\r
-                       // defining recursively any types we need:\r
-                       \r
-                       if (!Parameters.ComputeAndDefineParameterTypes (this))\r
-                               return false;\r
-                       \r
-                       param_types = Parameters.GetParameterInfo (this);\r
-                       if (param_types == null)\r
-                               return false;\r
-\r
-                       //\r
-                       // Invoke method\r
-                       //\r
-\r
-                       // Check accessibility\r
-                       foreach (Type partype in param_types){\r
-                               if (!container.AsAccessible (partype, ModFlags)) {\r
-                                       Report.Error (59, Location,\r
-                                                     "Inconsistent accessibility: parameter type `" +\r
-                                                     TypeManager.CSharpName (partype) + "` is less " +\r
-                                                     "accessible than delegate `" + Name + "'");\r
-                                       return false;\r
-                               }\r
-                               if (partype.IsPointer && !UnsafeOK (container))\r
-                                       return false;\r
-                       }\r
-                       \r
-                       ReturnType = ResolveTypeExpr (ReturnType, false, Location);\r
-                       ret_type = ReturnType.Type;\r
-                       if (ret_type == null)\r
-                               return false;\r
-\r
-                       if (!container.AsAccessible (ret_type, ModFlags)) {\r
-                               Report.Error (58, Location,\r
-                                             "Inconsistent accessibility: return type `" +\r
-                                             TypeManager.CSharpName (ret_type) + "` is less " +\r
-                                             "accessible than delegate `" + Name + "'");\r
-                               return false;\r
-                       }\r
-\r
-                       if (ret_type.IsPointer && !UnsafeOK (container))\r
-                               return false;\r
-\r
-                       //\r
-                       // We don't have to check any others because they are all\r
-                       // guaranteed to be accessible - they are standard types.\r
-                       //\r
-                       \r
-                       CallingConventions cc = Parameters.GetCallingConvention ();\r
-\r
-                       mattr = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual;\r
-\r
-                       InvokeBuilder = TypeBuilder.DefineMethod ("Invoke", \r
-                                                                 mattr,                     \r
-                                                                 cc,\r
-                                                                 ret_type,                  \r
-                                                                 param_types);\r
-\r
-                       //\r
-                       // Define parameters, and count out/ref parameters\r
-                       //\r
-                       int out_params = 0;\r
-                       i = 0;\r
-                       if (Parameters.FixedParameters != null){\r
-                               int top = Parameters.FixedParameters.Length;\r
-                               Parameter p;\r
-                               \r
-                               for (; i < top; i++) {\r
-                                       p = Parameters.FixedParameters [i];\r
-                                       pb = InvokeBuilder.DefineParameter (i+1, p.Attributes, p.Name);\r
-                                       cattr = p.OptAttributes;\r
-                                       if (cattr != null)\r
-                                               Attribute.ApplyAttributes (ec, pb, pb, cattr);\r
-\r
-                                       if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0)\r
-                                               out_params++;\r
-                               }\r
-                       }\r
-                       if (Parameters.ArrayParameter != null){\r
-                               Parameter p = Parameters.ArrayParameter;\r
-                               \r
-                               pb = InvokeBuilder.DefineParameter (\r
-                                       i+1, p.Attributes, p.Name);\r
-                               cattr = p.OptAttributes;\r
-                               if (cattr != null)\r
-                                       Attribute.ApplyAttributes (ec, pb, pb, cattr);\r
-                       }\r
-                       \r
-                       InvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);\r
-\r
-                       TypeManager.RegisterMethod (InvokeBuilder,\r
-                                                   new InternalParameters (container, Parameters),\r
-                                                   param_types);\r
-\r
-                       //\r
-                       // BeginInvoke\r
-                       //\r
-                       int params_num = param_types.Length;\r
-                       Type [] async_param_types = new Type [params_num + 2];\r
-\r
-                       param_types.CopyTo (async_param_types, 0);\r
-\r
-                       async_param_types [params_num] = TypeManager.asynccallback_type;\r
-                       async_param_types [params_num + 1] = TypeManager.object_type;\r
-\r
-                       mattr = MethodAttributes.Public | MethodAttributes.HideBySig |\r
-                               MethodAttributes.Virtual | MethodAttributes.NewSlot;\r
-                       \r
-                       BeginInvokeBuilder = TypeBuilder.DefineMethod ("BeginInvoke",\r
-                                                                      mattr,\r
-                                                                      cc,\r
-                                                                      TypeManager.iasyncresult_type,\r
-                                                                      async_param_types);\r
-\r
-                       i = 0;\r
-                       if (Parameters.FixedParameters != null){\r
-                               int top = Parameters.FixedParameters.Length;\r
-                               Parameter p;\r
-                               \r
-                               for (i = 0 ; i < top; i++) {\r
-                                       p = Parameters.FixedParameters [i];\r
-\r
-                                       pb = BeginInvokeBuilder.DefineParameter (i+1, p.Attributes, p.Name);\r
-                                       cattr = p.OptAttributes;\r
-                                       if (cattr != null)\r
-                                               Attribute.ApplyAttributes (ec, pb, pb, cattr);\r
-                               }\r
-                       }\r
-                       if (Parameters.ArrayParameter != null){\r
-                               Parameter p = Parameters.ArrayParameter;\r
-                               \r
-                               pb = BeginInvokeBuilder.DefineParameter (i+1, p.Attributes, p.Name);\r
-                               cattr = p.OptAttributes;\r
-                               if (cattr != null)\r
-                                       Attribute.ApplyAttributes (ec, pb, pb, cattr);\r
-                               i++;\r
-                       }\r
-\r
-                       BeginInvokeBuilder.DefineParameter (i + 1, ParameterAttributes.None, "callback");\r
-                       BeginInvokeBuilder.DefineParameter (i + 2, ParameterAttributes.None, "object");\r
-                       \r
-                       BeginInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);\r
-\r
-                       Parameter [] async_params = new Parameter [params_num + 2];\r
-                       int n = 0;\r
-                       if (Parameters.FixedParameters != null){\r
-                               Parameters.FixedParameters.CopyTo (async_params, 0);\r
-                               n = Parameters.FixedParameters.Length;\r
-                       }\r
-                       if (Parameters.ArrayParameter != null)\r
-                               async_params [n] = Parameters.ArrayParameter;\r
-                       \r
-                       async_params [params_num] = new Parameter (\r
-                               TypeManager.system_asynccallback_expr, "callback",\r
-                                                                  Parameter.Modifier.NONE, null);\r
-                       async_params [params_num + 1] = new Parameter (\r
-                               TypeManager.system_object_expr, "object",\r
-                                                                  Parameter.Modifier.NONE, null);\r
-\r
-                       Parameters async_parameters = new Parameters (async_params, null, Location);\r
-                       async_parameters.ComputeAndDefineParameterTypes (this);\r
-                       \r
-                       async_parameters.ComputeAndDefineParameterTypes (this);\r
-                       TypeManager.RegisterMethod (BeginInvokeBuilder,\r
-                                                   new InternalParameters (container, async_parameters),\r
-                                                   async_param_types);\r
-\r
-                       //\r
-                       // EndInvoke is a bit more interesting, all the parameters labeled as\r
-                       // out or ref have to be duplicated here.\r
-                       //\r
-                       \r
-                       Type [] end_param_types = new Type [out_params + 1];\r
-                       Parameter [] end_params = new Parameter [out_params + 1];\r
-                       int param = 0; \r
-                       if (out_params > 0){\r
-                               int top = Parameters.FixedParameters.Length;\r
-                               for (i = 0; i < top; i++){\r
-                                       Parameter p = Parameters.FixedParameters [i];\r
-                                       if ((p.ModFlags & Parameter.Modifier.ISBYREF) == 0)\r
-                                               continue;\r
-\r
-                                       end_param_types [param] = param_types [i];\r
-                                       end_params [param] = p;\r
-                                       param++;\r
-                               }\r
-                       }\r
-                       end_param_types [out_params] = TypeManager.iasyncresult_type;\r
-                       end_params [out_params] = new Parameter (TypeManager.system_iasyncresult_expr, "result", Parameter.Modifier.NONE, null);\r
-\r
-                       //\r
-                       // Create method, define parameters, register parameters with type system\r
-                       //\r
-                       EndInvokeBuilder = TypeBuilder.DefineMethod ("EndInvoke", mattr, cc, ret_type, end_param_types);\r
-                       EndInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);\r
-\r
-                       //\r
-                       // EndInvoke: Label the parameters\r
-                       //\r
-                       EndInvokeBuilder.DefineParameter (out_params + 1, ParameterAttributes.None, "result");\r
-                       for (i = 0; i < end_params.Length-1; i++){\r
-                               EndInvokeBuilder.DefineParameter (i + 1, end_params [i].Attributes, end_params [i].Name);\r
-                       }\r
-\r
-                       Parameters end_parameters = new Parameters (end_params, null, Location);\r
-                       end_parameters.ComputeAndDefineParameterTypes (this);\r
-\r
-                       TypeManager.RegisterMethod (\r
-                               EndInvokeBuilder,\r
-                               new InternalParameters (container, end_parameters),\r
-                               end_param_types);\r
-\r
-                       Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes);\r
-                       return true;\r
-               }\r
-\r
-               /// <summary>\r
-               ///  Verifies whether the method in question is compatible with the delegate\r
-               ///  Returns the method itself if okay and null if not.\r
-               /// </summary>\r
-               public static MethodBase VerifyMethod (EmitContext ec, Type delegate_type, MethodBase mb,\r
-                                                      Location loc)\r
-               {\r
-                       ParameterData pd = Invocation.GetParameterData (mb);\r
-\r
-                       int pd_count = pd.Count;\r
-\r
-                       Expression ml = Expression.MemberLookup (\r
-                               ec, delegate_type, "Invoke", loc);\r
-\r
-                       if (!(ml is MethodGroupExpr)) {\r
-                               Report.Error (-100, loc, "Internal error: could not find Invoke method!");\r
-                               return null;\r
-                       }\r
-\r
-                       MethodBase invoke_mb = ((MethodGroupExpr) ml).Methods [0];\r
-\r
-                       ParameterData invoke_pd = Invocation.GetParameterData (invoke_mb);\r
-\r
-                       if (invoke_pd.Count != pd_count)\r
-                               return null;\r
-\r
-                       for (int i = pd_count; i > 0; ) {\r
-                               i--;\r
-\r
-                               if (invoke_pd.ParameterType (i) == pd.ParameterType (i) &&\r
-                                   invoke_pd.ParameterModifier (i) == pd.ParameterModifier (i))\r
-                                       continue;\r
-                               else {\r
-                                       return null;\r
-                               }\r
-                       }\r
-\r
-                       if (((MethodInfo) invoke_mb).ReturnType == ((MethodInfo) mb).ReturnType)\r
-                               return mb;\r
-                       else\r
-                               return null;\r
-               }\r
-\r
-               // <summary>\r
-               //  Verifies whether the invocation arguments are compatible with the\r
-               //  delegate's target method\r
-               // </summary>\r
-               public static bool VerifyApplicability (EmitContext ec,\r
-                                                       Type delegate_type,\r
-                                                       ArrayList args,\r
-                                                       Location loc)\r
-               {\r
-                       int arg_count;\r
-\r
-                       if (args == null)\r
-                               arg_count = 0;\r
-                       else\r
-                               arg_count = args.Count;\r
-\r
-                       Expression ml = Expression.MemberLookup (\r
-                               ec, delegate_type, "Invoke", loc);\r
-\r
-                       if (!(ml is MethodGroupExpr)) {\r
-                               Report.Error (-100, loc, "Internal error: could not find Invoke method!" + delegate_type);\r
-                               return false;\r
-                       }\r
-                       \r
-                       MethodBase mb = ((MethodGroupExpr) ml).Methods [0];\r
-                       ParameterData pd = Invocation.GetParameterData (mb);\r
-\r
-                       int pd_count = pd.Count;\r
-\r
-                       bool not_params_method = (pd_count == 0) ||\r
-                               (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS);\r
-\r
-                       if (not_params_method && pd_count != arg_count) {\r
-                               Report.Error (1593, loc,\r
-                                             "Delegate '" + delegate_type.ToString ()\r
-                                             + "' does not take '" + arg_count + "' arguments");\r
-                               return false;\r
-                       }\r
-\r
-                       return Invocation.VerifyArgumentsCompat (ec, args, arg_count, mb, !not_params_method,\r
-                                                                delegate_type, loc);\r
-               }\r
-               \r
-               /// <summary>\r
-               ///  Verifies whether the delegate in question is compatible with this one in\r
-               ///  order to determine if instantiation from the same is possible.\r
-               /// </summary>\r
-               public static bool VerifyDelegate (EmitContext ec, Type delegate_type, Type probe_type, Location loc)\r
-               {\r
-                       Expression ml = Expression.MemberLookup (\r
-                               ec, delegate_type, "Invoke", loc);\r
-                       \r
-                       if (!(ml is MethodGroupExpr)) {\r
-                               Report.Error (-100, loc, "Internal error: could not find Invoke method!");\r
-                               return false;\r
-                       }\r
-                       \r
-                       MethodBase mb = ((MethodGroupExpr) ml).Methods [0];\r
-                       ParameterData pd = Invocation.GetParameterData (mb);\r
-\r
-                       Expression probe_ml = Expression.MemberLookup (\r
-                               ec, delegate_type, "Invoke", loc);\r
-                       \r
-                       if (!(probe_ml is MethodGroupExpr)) {\r
-                               Report.Error (-100, loc, "Internal error: could not find Invoke method!");\r
-                               return false;\r
-                       }\r
-                       \r
-                       MethodBase probe_mb = ((MethodGroupExpr) probe_ml).Methods [0];\r
-                       ParameterData probe_pd = Invocation.GetParameterData (probe_mb);\r
-                       \r
-                       if (((MethodInfo) mb).ReturnType != ((MethodInfo) probe_mb).ReturnType)\r
-                               return false;\r
-\r
-                       if (pd.Count != probe_pd.Count)\r
-                               return false;\r
-\r
-                       for (int i = pd.Count; i > 0; ) {\r
-                               i--;\r
-\r
-                               if (pd.ParameterType (i) != probe_pd.ParameterType (i) ||\r
-                                   pd.ParameterModifier (i) != probe_pd.ParameterModifier (i))\r
-                                       return false;\r
-                       }\r
-                       \r
-                       return true;\r
-               }\r
-               \r
-               public static string FullDelegateDesc (Type del_type, MethodBase mb, ParameterData pd)\r
-               {\r
-                       StringBuilder sb = new StringBuilder (TypeManager.CSharpName (((MethodInfo) mb).ReturnType));\r
-                       \r
-                       sb.Append (" " + del_type.ToString ());\r
-                       sb.Append (" (");\r
-\r
-                       int length = pd.Count;\r
-                       \r
-                       for (int i = length; i > 0; ) {\r
-                               i--;\r
-\r
-                               sb.Append (pd.ParameterDesc (length - i - 1));\r
-                               if (i != 0)\r
-                                       sb.Append (", ");\r
-                       }\r
-                       \r
-                       sb.Append (")");\r
-                       return sb.ToString ();\r
-                       \r
-               }\r
-               \r
-               // Hack around System.Reflection as found everywhere else\r
-               public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,\r
-                                                       MemberFilter filter, object criteria)\r
-               {\r
-                       ArrayList members = new ArrayList ();\r
-\r
-                       if ((mt & MemberTypes.Method) != 0) {\r
-                               if (ConstructorBuilder != null)\r
-                               if (filter (ConstructorBuilder, criteria))\r
-                                       members.Add (ConstructorBuilder);\r
-\r
-                               if (InvokeBuilder != null)\r
-                               if (filter (InvokeBuilder, criteria))\r
-                                       members.Add (InvokeBuilder);\r
-\r
-                               if (BeginInvokeBuilder != null)\r
-                               if (filter (BeginInvokeBuilder, criteria))\r
-                                       members.Add (BeginInvokeBuilder);\r
-\r
-                               if (EndInvokeBuilder != null)\r
-                               if (filter (EndInvokeBuilder, criteria))\r
-                                       members.Add (EndInvokeBuilder);\r
-                       }\r
-\r
-                       return new MemberList (members);\r
-               }\r
-\r
-               public override MemberCache MemberCache {\r
-                       get {\r
-                               return null;\r
-                       }\r
-               }\r
-\r
-               public Expression InstanceExpression {\r
-                       get {\r
-                               return instance_expr;\r
-                       }\r
-                       set {\r
-                               instance_expr = value;\r
-                       }\r
-               }\r
-\r
-               public MethodBase TargetMethod {\r
-                       get {\r
-                               return delegate_method;\r
-                       }\r
-                       set {\r
-                               delegate_method = value;\r
-                       }\r
-               }\r
-\r
-               public Type TargetReturnType {\r
-                       get {\r
-                               return ret_type;\r
-                       }\r
-               }\r
-\r
-               public Type [] ParameterTypes {\r
-                       get {\r
-                               return param_types;\r
-                       }\r
-               }\r
-               \r
-       }\r
-\r
-       //\r
-       // Base class for `NewDelegate' and `ImplicitDelegateCreation'\r
-       //\r
-       public abstract class DelegateCreation : Expression {\r
-               protected MethodBase constructor_method;\r
-               protected MethodBase delegate_method;\r
-               protected Expression delegate_instance_expr;\r
-\r
-               public DelegateCreation () {}\r
-\r
-               public static void Error_NoMatchingMethodForDelegate (MethodGroupExpr mg, Type t, MethodBase method, Location loc)\r
-               {\r
-                       string method_desc;\r
-                       \r
-                       if (mg.Methods.Length > 1)\r
-                               method_desc = mg.Methods [0].Name;\r
-                       else\r
-                               method_desc = Invocation.FullMethodDesc (mg.Methods [0]);\r
-\r
-                       ParameterData param = Invocation.GetParameterData (method);\r
-                       string delegate_desc = Delegate.FullDelegateDesc (t, method, param);\r
-                       \r
-                       Report.Error (123, loc, "Method '" + method_desc + "' does not " +\r
-                                     "match delegate '" + delegate_desc + "'");\r
-               }\r
-               \r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       if (delegate_instance_expr == null ||\r
-                           delegate_method.IsStatic)\r
-                               ec.ig.Emit (OpCodes.Ldnull);\r
-                       else\r
-                               delegate_instance_expr.Emit (ec);\r
-                       \r
-                       if (delegate_method.IsVirtual) {\r
-                               ec.ig.Emit (OpCodes.Dup);\r
-                               ec.ig.Emit (OpCodes.Ldvirtftn, (MethodInfo) delegate_method);\r
-                       } else\r
-                               ec.ig.Emit (OpCodes.Ldftn, (MethodInfo) delegate_method);\r
-                       ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) constructor_method);\r
-               }\r
-\r
-               protected bool ResolveConstructorMethod (EmitContext ec)\r
-               {\r
-                       Expression ml = Expression.MemberLookup (\r
-                               ec, type, ".ctor", loc);\r
-\r
-                       if (!(ml is MethodGroupExpr)) {\r
-                               Report.Error (-100, loc, "Internal error: Could not find delegate constructor!");\r
-                               return false;\r
-                       }\r
-\r
-                       constructor_method = ((MethodGroupExpr) ml).Methods [0];\r
-                       return true;\r
-               }\r
-\r
-               protected Expression ResolveMethodGroupExpr (EmitContext ec, MethodGroupExpr mg)\r
-               {\r
-                       foreach (MethodInfo mi in mg.Methods){\r
-                               delegate_method  = Delegate.VerifyMethod (ec, type, mi, loc);\r
-                               \r
-                               if (delegate_method != null)\r
-                                       break;\r
-                       }\r
-                       \r
-                       if (delegate_method == null) {\r
-                               Error_NoMatchingMethodForDelegate (mg, type, delegate_method, loc);\r
-                               return null;\r
-                       }\r
-                       \r
-                       //\r
-                       // Check safe/unsafe of the delegate\r
-                       //\r
-                       if (!ec.InUnsafe){\r
-                               ParameterData param = Invocation.GetParameterData (delegate_method);\r
-                               int count = param.Count;\r
-                               \r
-                               for (int i = 0; i < count; i++){\r
-                                       if (param.ParameterType (i).IsPointer){\r
-                                               Expression.UnsafeError (loc);\r
-                                               return null;\r
-                                       }\r
-                               }\r
-                       }\r
-                       \r
-                       if (mg.InstanceExpression != null)\r
-                               delegate_instance_expr = mg.InstanceExpression.Resolve (ec);\r
-                       else {\r
-                               if (ec.IsStatic){\r
-                                       if (!delegate_method.IsStatic){\r
-                                               Report.Error (120, loc,\r
-                                                             "An object reference is required for the non-static method " +\r
-                                                             delegate_method.Name);\r
-                                               return null;\r
-                                       }\r
-                                       delegate_instance_expr = null;\r
-                               } else\r
-                                       delegate_instance_expr = ec.GetThis (loc);\r
-                       }\r
-                       \r
-                       if (delegate_instance_expr != null)\r
-                               if (delegate_instance_expr.Type.IsValueType)\r
-                                       delegate_instance_expr = new BoxedCast (delegate_instance_expr);\r
-                       \r
-                       eclass = ExprClass.Value;\r
-                       return this;\r
-               }\r
-       }\r
-\r
-       //\r
-       // Created from the conversion code\r
-       //\r
-       public class ImplicitDelegateCreation : DelegateCreation {\r
-\r
-               ImplicitDelegateCreation (Type t, Location l)\r
-               {\r
-                       type = t;\r
-                       loc = l;\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       return this;\r
-               }\r
-               \r
-               static public Expression Create (EmitContext ec, MethodGroupExpr mge, Type target_type, Location loc)\r
-               {\r
-                       ImplicitDelegateCreation d = new ImplicitDelegateCreation (target_type, loc);\r
-                       if (d.ResolveConstructorMethod (ec))\r
-                               return d.ResolveMethodGroupExpr (ec, mge);\r
-                       else\r
-                               return null;\r
-               }\r
-       }\r
-       \r
-       //\r
-       // A delegate-creation-expression, invoked from the `New' class \r
-       //\r
-       public class NewDelegate : DelegateCreation {\r
-               public ArrayList Arguments;\r
-\r
-               //\r
-               // This constructor is invoked from the `New' expression\r
-               //\r
-               public NewDelegate (Type type, ArrayList Arguments, Location loc)\r
-               {\r
-                       this.type = type;\r
-                       this.Arguments = Arguments;\r
-                       this.loc  = loc; \r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       if (Arguments == null || Arguments.Count != 1) {\r
-                               Report.Error (149, loc,\r
-                                             "Method name expected");\r
-                               return null;\r
-                       }\r
-\r
-                       if (!ResolveConstructorMethod (ec))\r
-                               return null;\r
-\r
-                       Argument a = (Argument) Arguments [0];\r
-                       \r
-                       Expression invoke_method = Expression.MemberLookup (\r
-                               ec, type, "Invoke", MemberTypes.Method,\r
-                               Expression.AllBindingFlags, loc);\r
-\r
-                       if (invoke_method == null) {\r
-                               Report.Error (-200, loc, "Internal error ! Could not find Invoke method!");\r
-                               return null;\r
-                       }\r
-\r
-                       if (!a.ResolveMethodGroup (ec, loc))\r
-                               return null;\r
-                       \r
-                       Expression e = a.Expr;\r
-\r
-                       MethodGroupExpr mg = e as MethodGroupExpr;\r
-                       if (mg != null)\r
-                               return ResolveMethodGroupExpr (ec, mg);\r
-\r
-                       Type e_type = e.Type;\r
-\r
-                       if (!TypeManager.IsDelegateType (e_type)) {\r
-                               e.Error_UnexpectedKind ("method");\r
-                               return null;\r
-                       }\r
-\r
-                       // This is what MS' compiler reports. We could always choose\r
-                       // to be more verbose and actually give delegate-level specifics\r
-                       \r
-                       if (!Delegate.VerifyDelegate (ec, type, e_type, loc)) {\r
-                               Report.Error (29, loc, "Cannot implicitly convert type '" + e_type + "' " +\r
-                                             "to type '" + type + "'");\r
-                               return null;\r
-                       }\r
-                               \r
-                       delegate_instance_expr = e;\r
-                       delegate_method = ((MethodGroupExpr) invoke_method).Methods [0];\r
-                       \r
-                       eclass = ExprClass.Value;\r
-                       return this;\r
-               }\r
-               \r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       if (delegate_instance_expr == null || delegate_method.IsStatic)\r
-                               ec.ig.Emit (OpCodes.Ldnull);\r
-                       else\r
-                               delegate_instance_expr.Emit (ec);\r
-                       \r
-                       if (delegate_method.IsVirtual) {\r
-                               ec.ig.Emit (OpCodes.Dup);\r
-                               ec.ig.Emit (OpCodes.Ldvirtftn, (MethodInfo) delegate_method);\r
-                       } else\r
-                               ec.ig.Emit (OpCodes.Ldftn, (MethodInfo) delegate_method);\r
-                       ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) constructor_method);\r
-               }\r
-       }\r
-\r
-       public class DelegateInvocation : ExpressionStatement {\r
-\r
-               public Expression InstanceExpr;\r
-               public ArrayList  Arguments;\r
-\r
-               MethodBase method;\r
-               \r
-               public DelegateInvocation (Expression instance_expr, ArrayList args, Location loc)\r
-               {\r
-                       this.InstanceExpr = instance_expr;\r
-                       this.Arguments = args;\r
-                       this.loc = loc;\r
-               }\r
-\r
-               public override Expression DoResolve (EmitContext ec)\r
-               {\r
-                       if (InstanceExpr is EventExpr) {\r
-                               \r
-                               EventInfo ei = ((EventExpr) InstanceExpr).EventInfo;\r
-                               \r
-                               Expression ml = MemberLookup (\r
-                                       ec, ec.ContainerType, ei.Name,\r
-                                       MemberTypes.Event, AllBindingFlags | BindingFlags.DeclaredOnly, loc);\r
-\r
-                               if (ml == null) {\r
-                                       //\r
-                                       // If this is the case, then the Event does not belong \r
-                                       // to this Type and so, according to the spec\r
-                                       // cannot be accessed directly\r
-                                       //\r
-                                       // Note that target will not appear as an EventExpr\r
-                                       // in the case it is being referenced within the same type container;\r
-                                       // it will appear as a FieldExpr in that case.\r
-                                       //\r
-                                       \r
-                                       Assign.error70 (ei, loc);\r
-                                       return null;\r
-                               }\r
-                       }\r
-                       \r
-                       \r
-                       Type del_type = InstanceExpr.Type;\r
-                       if (del_type == null)\r
-                               return null;\r
-                       \r
-                       if (Arguments != null){\r
-                               foreach (Argument a in Arguments){\r
-                                       if (!a.Resolve (ec, loc))\r
-                                               return null;\r
-                               }\r
-                       }\r
-                       \r
-                       if (!Delegate.VerifyApplicability (ec, del_type, Arguments, loc))\r
-                               return null;\r
-\r
-                       Expression lookup = Expression.MemberLookup (ec, del_type, "Invoke", loc);\r
-                       if (!(lookup is MethodGroupExpr)) {\r
-                               Report.Error (-100, loc, "Internal error: could not find Invoke method!");\r
-                               return null;\r
-                       }\r
-                       \r
-                       method = ((MethodGroupExpr) lookup).Methods [0];\r
-                       type = ((MethodInfo) method).ReturnType;\r
-                       eclass = ExprClass.Value;\r
-                       \r
-                       return this;\r
-               }\r
-\r
-               public override void Emit (EmitContext ec)\r
-               {\r
-                       //\r
-                       // Invocation on delegates call the virtual Invoke member\r
-                       // so we are always `instance' calls\r
-                       //\r
-                       Invocation.EmitCall (ec, false, false, InstanceExpr, method, Arguments, loc);\r
-               }\r
-\r
-               public override void EmitStatement (EmitContext ec)\r
-               {\r
-                       Emit (ec);\r
-                       // \r
-                       // Pop the return value if there is one\r
-                       //\r
-                       if (method is MethodInfo){\r
-                               if (((MethodInfo) method).ReturnType != TypeManager.void_type)\r
-                                       ec.ig.Emit (OpCodes.Pop);\r
-                       }\r
-               }\r
-\r
-       }\r
-}\r
+               {
+                       this.ReturnType = type;
+                       ModFlags        = Modifiers.Check (AllowedModifiers, mod_flags,
+                                                          IsTopLevel ? Modifiers.INTERNAL :
+                                                          Modifiers.PRIVATE, l);
+                       Parameters      = param_list;
+               }
+
+               public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
+               {
+                       if (a.Target == AttributeTargets.ReturnValue) {
+                               if (return_attributes == null)
+                                       return_attributes = new ReturnParameter (InvokeBuilder, Location);
+
+                               return_attributes.ApplyAttributeBuilder (a, cb);
+                               return;
+                       }
+
+                       base.ApplyAttributeBuilder (a, cb);
+               }
+
+               public override TypeBuilder DefineType ()
+               {
+                       if (TypeBuilder != null)
+                               return TypeBuilder;
+
+                       ec = new EmitContext (this, this, Location, null, null, ModFlags, false);
+
+                       TypeAttributes attr = Modifiers.TypeAttr (ModFlags, IsTopLevel) |
+                               TypeAttributes.Class | TypeAttributes.Sealed;
+
+                       if (TypeManager.multicast_delegate_type == null)
+                               Report.Error (-100, loc, "Internal error: delegate used before " +
+                                             "System.MulticastDelegate is resolved.  This can only " +
+                                             "happen during corlib compilation, when using a delegate " +
+                                             "in any of the `core' classes.  See bug #72015 for details.");
+
+                       if (IsTopLevel) {
+                               if (TypeManager.NamespaceClash (Name, Location))
+                                       return null;
+                               
+                               ModuleBuilder builder = CodeGen.Module.Builder;
+
+                               TypeBuilder = builder.DefineType (
+                                       Name, attr, TypeManager.multicast_delegate_type);
+                       } else {
+                               TypeBuilder builder = Parent.TypeBuilder;
+
+                               string name = Name.Substring (1 + Name.LastIndexOf ('.'));
+                               TypeBuilder = builder.DefineNestedType (
+                                       name, attr, TypeManager.multicast_delegate_type);
+                       }
+
+                       TypeManager.AddDelegateType (Name, TypeBuilder, this);
+
+                       return TypeBuilder;
+               }
+
+               public override bool DefineMembers (TypeContainer container)
+               {
+                       return true;
+               }
+
+               public override bool Define ()
+               {
+                       MethodAttributes mattr;
+                       int i;
+                       ec = new EmitContext (this, this, Location, null, null, ModFlags, false);
+
+                       // FIXME: POSSIBLY make this static, as it is always constant
+                       //
+                       Type [] const_arg_types = new Type [2];
+                       const_arg_types [0] = TypeManager.object_type;
+                       const_arg_types [1] = TypeManager.intptr_type;
+
+                       mattr = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName |
+                               MethodAttributes.HideBySig | MethodAttributes.Public;
+
+                       ConstructorBuilder = TypeBuilder.DefineConstructor (mattr,
+                                                                           CallingConventions.Standard,
+                                                                           const_arg_types);
+
+                       ConstructorBuilder.DefineParameter (1, ParameterAttributes.None, "object");
+                       ConstructorBuilder.DefineParameter (2, ParameterAttributes.None, "method");
+                       //
+                       // HACK because System.Reflection.Emit is lame
+                       //
+                       //
+                       // FIXME: POSSIBLY make these static, as they are always the same
+                       Parameter [] fixed_pars = new Parameter [2];
+                       fixed_pars [0] = new Parameter (TypeManager.system_object_expr, "object",
+                                                       Parameter.Modifier.NONE, null);
+                       fixed_pars [1] = new Parameter (TypeManager.system_intptr_expr, "method", 
+                                                       Parameter.Modifier.NONE, null);
+                       Parameters const_parameters = new Parameters (fixed_pars, null, Location);
+                       
+                       TypeManager.RegisterMethod (
+                               ConstructorBuilder,
+                               new InternalParameters (const_arg_types, const_parameters),
+                               const_arg_types);
+                               
+                       
+                       ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
+
+                       //
+                       // Here the various methods like Invoke, BeginInvoke etc are defined
+                       //
+                       // First, call the `out of band' special method for
+                       // defining recursively any types we need:
+                       
+                       if (!Parameters.ComputeAndDefineParameterTypes (ec))
+                               return false;
+                       
+                       param_types = Parameters.GetParameterInfo (ec);
+                       if (param_types == null)
+                               return false;
+
+                       //
+                       // Invoke method
+                       //
+
+                       // Check accessibility
+                       foreach (Type partype in param_types){
+                               if (!Parent.AsAccessible (partype, ModFlags)) {
+                                       Report.Error (59, Location,
+                                                     "Inconsistent accessibility: parameter type `" +
+                                                     TypeManager.CSharpName (partype) + "` is less " +
+                                                     "accessible than delegate `" + Name + "'");
+                                       return false;
+                               }
+                               if (partype.IsPointer && !UnsafeOK (Parent))
+                                       return false;
+                       }
+                       
+                       ReturnType = ReturnType.ResolveAsTypeTerminal (ec, false);
+                        if (ReturnType == null)
+                            return false;
+                        
+                       ret_type = ReturnType.Type;
+                       if (ret_type == null)
+                               return false;
+
+                       if (!Parent.AsAccessible (ret_type, ModFlags)) {
+                               Report.Error (58, Location,
+                                             "Inconsistent accessibility: return type `" +
+                                             TypeManager.CSharpName (ret_type) + "` is less " +
+                                             "accessible than delegate `" + Name + "'");
+                               return false;
+                       }
+
+                       if (ret_type.IsPointer && !UnsafeOK (Parent))
+                               return false;
+
+                       //
+                       // We don't have to check any others because they are all
+                       // guaranteed to be accessible - they are standard types.
+                       //
+                       
+                       CallingConventions cc = Parameters.GetCallingConvention ();
+
+                       mattr = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual;
+
+                       InvokeBuilder = TypeBuilder.DefineMethod ("Invoke", 
+                                                                 mattr,                     
+                                                                 cc,
+                                                                 ret_type,                  
+                                                                 param_types);
+
+                       //
+                       // Define parameters, and count out/ref parameters
+                       //
+                       int out_params = 0;
+                       i = 0;
+                       if (Parameters.FixedParameters != null){
+                               int top = Parameters.FixedParameters.Length;
+                               Parameter p;
+                               
+                               for (; i < top; i++) {
+                                       p = Parameters.FixedParameters [i];
+                                       p.DefineParameter (ec, InvokeBuilder, null, i + 1, Location);
+
+                                       if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0)
+                                               out_params++;
+                               }
+                       }
+                       if (Parameters.ArrayParameter != null){
+                               Parameter p = Parameters.ArrayParameter;
+                               p.DefineParameter (ec, InvokeBuilder, null, i + 1, Location);
+                       }
+                       
+                       InvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
+
+                       TypeManager.RegisterMethod (InvokeBuilder,
+                                                   new InternalParameters (param_types, Parameters),
+                                                   param_types);
+
+                       //
+                       // BeginInvoke
+                       //
+                       int params_num = param_types.Length;
+                       Type [] async_param_types = new Type [params_num + 2];
+
+                       param_types.CopyTo (async_param_types, 0);
+
+                       async_param_types [params_num] = TypeManager.asynccallback_type;
+                       async_param_types [params_num + 1] = TypeManager.object_type;
+
+                       mattr = MethodAttributes.Public | MethodAttributes.HideBySig |
+                               MethodAttributes.Virtual | MethodAttributes.NewSlot;
+                       
+                       BeginInvokeBuilder = TypeBuilder.DefineMethod ("BeginInvoke",
+                                                                      mattr,
+                                                                      cc,
+                                                                      TypeManager.iasyncresult_type,
+                                                                      async_param_types);
+
+                       i = 0;
+                       if (Parameters.FixedParameters != null){
+                               int top = Parameters.FixedParameters.Length;
+                               Parameter p;
+                               
+                               for (i = 0 ; i < top; i++) {
+                                       p = Parameters.FixedParameters [i];
+
+                                       p.DefineParameter (ec, BeginInvokeBuilder, null, i + 1, Location);
+                               }
+                       }
+                       if (Parameters.ArrayParameter != null){
+                               Parameter p = Parameters.ArrayParameter;
+                               p.DefineParameter (ec, BeginInvokeBuilder, null, i + 1, Location);
+
+                               i++;
+                       }
+
+                       BeginInvokeBuilder.DefineParameter (i + 1, ParameterAttributes.None, "callback");
+                       BeginInvokeBuilder.DefineParameter (i + 2, ParameterAttributes.None, "object");
+                       
+                       BeginInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
+
+                       Parameter [] async_params = new Parameter [params_num + 2];
+                       int n = 0;
+                       if (Parameters.FixedParameters != null){
+                               Parameters.FixedParameters.CopyTo (async_params, 0);
+                               n = Parameters.FixedParameters.Length;
+                       }
+                       if (Parameters.ArrayParameter != null)
+                               async_params [n] = Parameters.ArrayParameter;
+                       
+                       async_params [params_num] = new Parameter (
+                               TypeManager.system_asynccallback_expr, "callback",
+                                                                  Parameter.Modifier.NONE, null);
+                       async_params [params_num + 1] = new Parameter (
+                               TypeManager.system_object_expr, "object",
+                                                                  Parameter.Modifier.NONE, null);
+
+                       Parameters async_parameters = new Parameters (async_params, null, Location);
+                       async_parameters.ComputeAndDefineParameterTypes (ec);
+
+                       TypeManager.RegisterMethod (BeginInvokeBuilder,
+                                                   new InternalParameters (async_param_types, async_parameters),
+                                                   async_param_types);
+
+                       //
+                       // EndInvoke is a bit more interesting, all the parameters labeled as
+                       // out or ref have to be duplicated here.
+                       //
+                       
+                       Type [] end_param_types = new Type [out_params + 1];
+                       Parameter [] end_params = new Parameter [out_params + 1];
+                       int param = 0; 
+                       if (out_params > 0){
+                               int top = Parameters.FixedParameters.Length;
+                               for (i = 0; i < top; i++){
+                                       Parameter p = Parameters.FixedParameters [i];
+                                       if ((p.ModFlags & Parameter.Modifier.ISBYREF) == 0)
+                                               continue;
+
+                                       end_param_types [param] = param_types [i];
+                                       end_params [param] = p;
+                                       param++;
+                               }
+                       }
+                       end_param_types [out_params] = TypeManager.iasyncresult_type;
+                       end_params [out_params] = new Parameter (TypeManager.system_iasyncresult_expr, "result", Parameter.Modifier.NONE, null);
+
+                       //
+                       // Create method, define parameters, register parameters with type system
+                       //
+                       EndInvokeBuilder = TypeBuilder.DefineMethod ("EndInvoke", mattr, cc, ret_type, end_param_types);
+                       EndInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
+
+                       //
+                       // EndInvoke: Label the parameters
+                       //
+                       EndInvokeBuilder.DefineParameter (out_params + 1, ParameterAttributes.None, "result");
+                       for (i = 0; i < end_params.Length-1; i++){
+                               EndInvokeBuilder.DefineParameter (i + 1, end_params [i].Attributes, end_params [i].Name);
+                       }
+
+                       Parameters end_parameters = new Parameters (end_params, null, Location);
+                       end_parameters.ComputeAndDefineParameterTypes (ec);
+
+                       TypeManager.RegisterMethod (
+                               EndInvokeBuilder,
+                               new InternalParameters (end_param_types, end_parameters),
+                               end_param_types);
+
+                       return true;
+               }
+
+               public override void Emit ()
+               {
+                       if (OptAttributes != null) {
+                               Parameters.LabelParameters (ec, InvokeBuilder, Location);
+                               OptAttributes.Emit (ec, this);
+                       }
+
+                       base.Emit ();
+               }
+
+               public override string[] ValidAttributeTargets {
+                       get {
+                               return attribute_targets;
+                       }
+               }
+
+               //TODO: duplicate
+               protected override bool VerifyClsCompliance (DeclSpace ds)
+               {
+                       if (!base.VerifyClsCompliance (ds)) {
+                               return false;
+                       }
+
+                       AttributeTester.AreParametersCompliant (Parameters.FixedParameters, Location);
+
+                       if (!AttributeTester.IsClsCompliant (ReturnType.Type)) {
+                               Report.Error (3002, Location, "Return type of '{0}' is not CLS-compliant", GetSignatureForError ());
+                       }
+                       return true;
+               }
+
+               //
+               // Returns the MethodBase for "Invoke" from a delegate type, this is used
+               // to extract the signature of a delegate.
+               //
+               public static MethodInfo GetInvokeMethod (EmitContext ec, Type delegate_type, Location loc)
+               {
+                       Expression ml = Expression.MemberLookup (
+                               ec, delegate_type, "Invoke", loc);
+
+                       if (!(ml is MethodGroupExpr)) {
+                               Report.Error (-100, loc, "Internal error: could not find Invoke method!");
+                               return null;
+                       }
+
+                       return (MethodInfo) (((MethodGroupExpr) ml).Methods [0]);
+               }
+               
+               /// <summary>
+               ///  Verifies whether the method in question is compatible with the delegate
+               ///  Returns the method itself if okay and null if not.
+               /// </summary>
+               public static MethodBase VerifyMethod (EmitContext ec, Type delegate_type, MethodBase mb,
+                                                      Location loc)
+               {
+                       ParameterData pd = Invocation.GetParameterData (mb);
+
+                       int pd_count = pd.Count;
+
+                       MethodBase invoke_mb = GetInvokeMethod (ec, delegate_type, loc);
+                       if (invoke_mb == null)
+                               return null;
+
+                       ParameterData invoke_pd = Invocation.GetParameterData (invoke_mb);
+
+                       if (invoke_pd.Count != pd_count)
+                               return null;
+
+                       for (int i = pd_count; i > 0; ) {
+                               i--;
+
+                               Type invoke_pd_type = invoke_pd.ParameterType (i);
+                               Type pd_type = pd.ParameterType (i);
+                               Parameter.Modifier invoke_pd_type_mod = invoke_pd.ParameterModifier (i);
+                               Parameter.Modifier pd_type_mod = pd.ParameterModifier (i);
+
+                               if (invoke_pd_type == pd_type &&
+                                   invoke_pd_type_mod == pd_type_mod)
+                                       continue;
+                               
+                               if (invoke_pd_type.IsSubclassOf (pd_type) && 
+                                               invoke_pd_type_mod == pd_type_mod)
+                                       if (RootContext.Version == LanguageVersion.ISO_1) {
+                                               Report.FeatureIsNotStandardized (loc, "contravariance");
+                                               return null;
+                                       } else
+                                               continue;
+                                       
+                               return null;
+                       }
+
+                       Type invoke_mb_retval = ((MethodInfo) invoke_mb).ReturnType;
+                       Type mb_retval = ((MethodInfo) mb).ReturnType;
+                       if (invoke_mb_retval == mb_retval)
+                               return mb;
+                       
+                       if (mb_retval.IsSubclassOf (invoke_mb_retval))
+                               if (RootContext.Version == LanguageVersion.ISO_1) {
+                                       Report.FeatureIsNotStandardized (loc, "covariance");
+                                       return null;
+                               }
+                               else
+                                       return mb;
+                       
+                       return null;
+               }
+
+               // <summary>
+               //  Verifies whether the invocation arguments are compatible with the
+               //  delegate's target method
+               // </summary>
+               public static bool VerifyApplicability (EmitContext ec, Type delegate_type,
+                                                       ArrayList args, Location loc)
+               {
+                       int arg_count;
+
+                       if (args == null)
+                               arg_count = 0;
+                       else
+                               arg_count = args.Count;
+
+                       Expression ml = Expression.MemberLookup (
+                               ec, delegate_type, "Invoke", loc);
+
+                       if (!(ml is MethodGroupExpr)) {
+                               Report.Error (-100, loc, "Internal error: could not find Invoke method!" + delegate_type);
+                               return false;
+                       }
+                       
+                       MethodBase mb = ((MethodGroupExpr) ml).Methods [0];
+                       ParameterData pd = Invocation.GetParameterData (mb);
+
+                       int pd_count = pd.Count;
+
+                       bool params_method = (pd_count != 0) &&
+                               (pd.ParameterModifier (pd_count - 1) == Parameter.Modifier.PARAMS);
+
+                       if (!params_method && pd_count != arg_count) {
+                               Report.Error (1593, loc,
+                                             "Delegate '{0}' does not take {1} arguments",
+                                             delegate_type.ToString (), arg_count);
+                               return false;
+                       }
+
+                       //
+                       // Consider the case:
+                       //   delegate void FOO(param object[] args);
+                       //   FOO f = new FOO(...);
+                       //   f(new object[] {1, 2, 3});
+                       //
+                       // This should be treated like f(1,2,3).  This is done by ignoring the 
+                       // 'param' modifier for that invocation.  If that fails, then the
+                       // 'param' modifier is considered.
+                       //
+                       // One issue is that 'VerifyArgumentsCompat' modifies the elements of
+                       // the 'args' array.  However, the modifications appear idempotent.
+                       // Normal 'Invocation's also have the same behaviour, implicitly.
+                       //
+
+                       bool ans = false;
+                       if (arg_count == pd_count)
+                               ans = Invocation.VerifyArgumentsCompat (
+                                       ec, args, arg_count, mb, false,
+                                       delegate_type, false, loc);
+                       if (!ans && params_method)
+                               ans = Invocation.VerifyArgumentsCompat (
+                                       ec, args, arg_count, mb, true,
+                                       delegate_type, false, loc);
+                       return ans;
+               }
+               
+               /// <summary>
+               ///  Verifies whether the delegate in question is compatible with this one in
+               ///  order to determine if instantiation from the same is possible.
+               /// </summary>
+               public static bool VerifyDelegate (EmitContext ec, Type delegate_type, Type probe_type, Location loc)
+               {
+                       Expression ml = Expression.MemberLookup (
+                               ec, delegate_type, "Invoke", loc);
+                       
+                       if (!(ml is MethodGroupExpr)) {
+                               Report.Error (-100, loc, "Internal error: could not find Invoke method!");
+                               return false;
+                       }
+                       
+                       MethodBase mb = ((MethodGroupExpr) ml).Methods [0];
+                       ParameterData pd = Invocation.GetParameterData (mb);
+
+                       Expression probe_ml = Expression.MemberLookup (
+                               ec, delegate_type, "Invoke", loc);
+                       
+                       if (!(probe_ml is MethodGroupExpr)) {
+                               Report.Error (-100, loc, "Internal error: could not find Invoke method!");
+                               return false;
+                       }
+                       
+                       MethodBase probe_mb = ((MethodGroupExpr) probe_ml).Methods [0];
+                       ParameterData probe_pd = Invocation.GetParameterData (probe_mb);
+                       
+                       if (((MethodInfo) mb).ReturnType != ((MethodInfo) probe_mb).ReturnType)
+                               return false;
+
+                       if (pd.Count != probe_pd.Count)
+                               return false;
+
+                       for (int i = pd.Count; i > 0; ) {
+                               i--;
+
+                               if (pd.ParameterType (i) != probe_pd.ParameterType (i) ||
+                                   pd.ParameterModifier (i) != probe_pd.ParameterModifier (i))
+                                       return false;
+                       }
+                       
+                       return true;
+               }
+               
+               public static string FullDelegateDesc (Type del_type, MethodBase mb, ParameterData pd)
+               {
+                       StringBuilder sb = new StringBuilder (TypeManager.CSharpName (((MethodInfo) mb).ReturnType));
+                       
+                       sb.Append (" " + del_type.ToString ());
+                       sb.Append (" (");
+
+                       int length = pd.Count;
+                       
+                       for (int i = length; i > 0; ) {
+                               i--;
+
+                               sb.Append (pd.ParameterDesc (length - i - 1));
+                               if (i != 0)
+                                       sb.Append (", ");
+                       }
+                       
+                       sb.Append (")");
+                       return sb.ToString ();
+                       
+               }
+               
+               // Hack around System.Reflection as found everywhere else
+               public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+                                                       MemberFilter filter, object criteria)
+               {
+                       ArrayList members = new ArrayList ();
+
+                       if ((mt & MemberTypes.Method) != 0) {
+                               if (ConstructorBuilder != null)
+                               if (filter (ConstructorBuilder, criteria))
+                                       members.Add (ConstructorBuilder);
+
+                               if (InvokeBuilder != null)
+                               if (filter (InvokeBuilder, criteria))
+                                       members.Add (InvokeBuilder);
+
+                               if (BeginInvokeBuilder != null)
+                               if (filter (BeginInvokeBuilder, criteria))
+                                       members.Add (BeginInvokeBuilder);
+
+                               if (EndInvokeBuilder != null)
+                               if (filter (EndInvokeBuilder, criteria))
+                                       members.Add (EndInvokeBuilder);
+                       }
+
+                       return new MemberList (members);
+               }
+
+               public override MemberCache MemberCache {
+                       get {
+                               return null;
+                       }
+               }
+
+               public Expression InstanceExpression {
+                       get {
+                               return instance_expr;
+                       }
+                       set {
+                               instance_expr = value;
+                       }
+               }
+
+               public MethodBase TargetMethod {
+                       get {
+                               return delegate_method;
+                       }
+                       set {
+                               delegate_method = value;
+                       }
+               }
+
+               public Type TargetReturnType {
+                       get {
+                               return ret_type;
+                       }
+               }
+
+               public Type [] ParameterTypes {
+                       get {
+                               return param_types;
+                       }
+               }
+
+               public override AttributeTargets AttributeTargets {
+                       get {
+                               return AttributeTargets.Delegate;
+                       }
+               }
+
+               //
+               //   Represents header string for documentation comment.
+               //
+               public override string DocCommentHeader {
+                       get { return "T:"; }
+               }
+
+               protected override void VerifyObsoleteAttribute()
+               {
+                       CheckUsageOfObsoleteAttribute (ret_type);
+
+                       foreach (Type type in param_types) {
+                               CheckUsageOfObsoleteAttribute (type);
+                       }
+               }
+       }
+
+       //
+       // Base class for `NewDelegate' and `ImplicitDelegateCreation'
+       //
+       public abstract class DelegateCreation : Expression {
+               protected MethodBase constructor_method;
+               protected MethodBase delegate_method;
+               protected MethodGroupExpr method_group;
+               protected Expression delegate_instance_expression;
+
+               public DelegateCreation () {}
+
+               public static void Error_NoMatchingMethodForDelegate (EmitContext ec, MethodGroupExpr mg, Type type, Location loc)
+               {
+                       string method_desc;
+                       
+                       if (mg.Methods.Length > 1)
+                               method_desc = mg.Methods [0].Name;
+                       else
+                               method_desc = Invocation.FullMethodDesc (mg.Methods [0]);
+
+                       Expression invoke_method = Expression.MemberLookup (
+                               ec, type, "Invoke", MemberTypes.Method,
+                               Expression.AllBindingFlags, loc);
+                       MethodBase method = ((MethodGroupExpr) invoke_method).Methods [0];
+                       ParameterData param = Invocation.GetParameterData (method);
+                       string delegate_desc = Delegate.FullDelegateDesc (type, method, param);
+                       
+                       Report.Error (123, loc, "Method '" + method_desc + "' does not " +
+                                     "match delegate '" + delegate_desc + "'");
+               }
+               
+               public override void Emit (EmitContext ec)
+               {
+                       if (delegate_instance_expression == null || delegate_method.IsStatic)
+                               ec.ig.Emit (OpCodes.Ldnull);
+                       else
+                               delegate_instance_expression.Emit (ec);
+                       
+                       if (delegate_method.IsVirtual && !method_group.IsBase) {
+                               ec.ig.Emit (OpCodes.Dup);
+                               ec.ig.Emit (OpCodes.Ldvirtftn, (MethodInfo) delegate_method);
+                       } else
+                               ec.ig.Emit (OpCodes.Ldftn, (MethodInfo) delegate_method);
+                       ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) constructor_method);
+               }
+
+               protected bool ResolveConstructorMethod (EmitContext ec)
+               {
+                       Expression ml = Expression.MemberLookup (
+                               ec, type, ".ctor", loc);
+
+                       if (!(ml is MethodGroupExpr)) {
+                               Report.Error (-100, loc, "Internal error: Could not find delegate constructor!");
+                               return false;
+                       }
+
+                       constructor_method = ((MethodGroupExpr) ml).Methods [0];
+                       return true;
+               }
+
+               protected Expression ResolveMethodGroupExpr (EmitContext ec, MethodGroupExpr mg)
+               {
+                       foreach (MethodInfo mi in mg.Methods){
+                               delegate_method  = Delegate.VerifyMethod (ec, type, mi, loc);
+                               
+                               if (delegate_method != null)
+                                       break;
+                       }
+                       
+                       if (delegate_method == null) {
+                               Error_NoMatchingMethodForDelegate (ec, mg, type, loc);
+                               return null;
+                       }
+                       
+                       //
+                       // Check safe/unsafe of the delegate
+                       //
+                       if (!ec.InUnsafe){
+                               ParameterData param = Invocation.GetParameterData (delegate_method);
+                               int count = param.Count;
+                               
+                               for (int i = 0; i < count; i++){
+                                       if (param.ParameterType (i).IsPointer){
+                                               Expression.UnsafeError (loc);
+                                               return null;
+                                       }
+                               }
+                       }
+                       
+                       //TODO: implement caching when performance will be low
+                       IMethodData md = TypeManager.GetMethod (delegate_method);
+                       if (md == null) {
+                               if (System.Attribute.GetCustomAttribute (delegate_method, TypeManager.conditional_attribute_type) != null) {
+                                       Report.Error (1618, loc, "Cannot create delegate with '{0}' because it has a Conditional attribute", TypeManager.CSharpSignature (delegate_method));
+                               }
+                       } else {
+                               if (md.OptAttributes != null && md.OptAttributes.Search (TypeManager.conditional_attribute_type, ec) != null) {
+                                       Report.Error (1618, loc, "Cannot create delegate with '{0}' because it has a Conditional attribute", TypeManager.CSharpSignature (delegate_method));
+                               }
+                       }
+                       
+                       if (mg.InstanceExpression != null)
+                               delegate_instance_expression = mg.InstanceExpression.Resolve (ec);
+                       else if (ec.IsStatic) {
+                               if (!delegate_method.IsStatic) {
+                                       Report.Error (120, loc,
+                                                     "An object reference is required for the non-static method " +
+                                                     delegate_method.Name);
+                                       return null;
+                               }
+                               delegate_instance_expression = null;
+                       } else
+                               delegate_instance_expression = ec.GetThis (loc);
+                       
+                       if (delegate_instance_expression != null && delegate_instance_expression.Type.IsValueType)
+                               delegate_instance_expression = new BoxedCast (delegate_instance_expression);
+                       
+                       method_group = mg;
+                       eclass = ExprClass.Value;
+                       return this;
+               }
+       }
+
+       //
+       // Created from the conversion code
+       //
+       public class ImplicitDelegateCreation : DelegateCreation {
+
+               ImplicitDelegateCreation (Type t, Location l)
+               {
+                       type = t;
+                       loc = l;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return this;
+               }
+               
+               static public Expression Create (EmitContext ec, MethodGroupExpr mge, Type target_type, Location loc)
+               {
+                       ImplicitDelegateCreation d = new ImplicitDelegateCreation (target_type, loc);
+                       if (d.ResolveConstructorMethod (ec))
+                               return d.ResolveMethodGroupExpr (ec, mge);
+                       else
+                               return null;
+               }
+       }
+
+       //
+       // A delegate-creation-expression, invoked from the `New' class 
+       //
+       public class NewDelegate : DelegateCreation {
+               public ArrayList Arguments;
+
+               //
+               // This constructor is invoked from the `New' expression
+               //
+               public NewDelegate (Type type, ArrayList Arguments, Location loc)
+               {
+                       this.type = type;
+                       this.Arguments = Arguments;
+                       this.loc  = loc; 
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       if (Arguments == null || Arguments.Count != 1) {
+                               Report.Error (149, loc,
+                                             "Method name expected");
+                               return null;
+                       }
+
+                       if (!ResolveConstructorMethod (ec))
+                               return null;
+
+                       Argument a = (Argument) Arguments [0];
+
+                       if (!a.ResolveMethodGroup (ec, loc))
+                               return null;
+                       
+                       Expression e = a.Expr;
+
+                       if (e is AnonymousMethod && RootContext.Version != LanguageVersion.ISO_1)
+                               return ((AnonymousMethod) e).Compatible (ec, type, false);
+
+                       MethodGroupExpr mg = e as MethodGroupExpr;
+                       if (mg != null)
+                               return ResolveMethodGroupExpr (ec, mg);
+
+                       Type e_type = e.Type;
+
+                       if (!TypeManager.IsDelegateType (e_type)) {
+                               Report.Error (149, loc, "Method name expected");
+                               return null;
+                       }
+
+                       method_group = Expression.MemberLookup (
+                               ec, type, "Invoke", MemberTypes.Method,
+                               Expression.AllBindingFlags, loc) as MethodGroupExpr;
+
+                       if (method_group == null) {
+                               Report.Error (-200, loc, "Internal error ! Could not find Invoke method!");
+                               return null;
+                       }
+
+                       // This is what MS' compiler reports. We could always choose
+                       // to be more verbose and actually give delegate-level specifics                        
+                       if (!Delegate.VerifyDelegate (ec, type, e_type, loc)) {
+                               Report.Error (29, loc, "Cannot implicitly convert type '" + e_type + "' " +
+                                             "to type '" + type + "'");
+                               return null;
+                       }
+                               
+                       delegate_instance_expression = e;
+                       delegate_method = method_group.Methods [0];
+                       
+                       eclass = ExprClass.Value;
+                       return this;
+               }
+       }
+
+       public class DelegateInvocation : ExpressionStatement {
+
+               public Expression InstanceExpr;
+               public ArrayList  Arguments;
+
+               MethodBase method;
+               
+               public DelegateInvocation (Expression instance_expr, ArrayList args, Location loc)
+               {
+                       this.InstanceExpr = instance_expr;
+                       this.Arguments = args;
+                       this.loc = loc;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       if (InstanceExpr is EventExpr) {
+                               
+                               EventInfo ei = ((EventExpr) InstanceExpr).EventInfo;
+                               
+                               Expression ml = MemberLookup (
+                                       ec, ec.ContainerType, ei.Name,
+                                       MemberTypes.Event, AllBindingFlags | BindingFlags.DeclaredOnly, loc);
+
+                               if (ml == null) {
+                                       //
+                                       // If this is the case, then the Event does not belong 
+                                       // to this Type and so, according to the spec
+                                       // cannot be accessed directly
+                                       //
+                                       // Note that target will not appear as an EventExpr
+                                       // in the case it is being referenced within the same type container;
+                                       // it will appear as a FieldExpr in that case.
+                                       //
+                                       
+                                       Assign.error70 (ei, loc);
+                                       return null;
+                               }
+                       }
+                       
+                       
+                       Type del_type = InstanceExpr.Type;
+                       if (del_type == null)
+                               return null;
+                       
+                       if (Arguments != null){
+                               foreach (Argument a in Arguments){
+                                       if (!a.Resolve (ec, loc))
+                                               return null;
+                               }
+                       }
+                       
+                       if (!Delegate.VerifyApplicability (ec, del_type, Arguments, loc))
+                               return null;
+
+                       Expression lookup = Expression.MemberLookup (ec, del_type, "Invoke", loc);
+                       if (!(lookup is MethodGroupExpr)) {
+                               Report.Error (-100, loc, "Internal error: could not find Invoke method!");
+                               return null;
+                       }
+                       
+                       method = ((MethodGroupExpr) lookup).Methods [0];
+                       type = ((MethodInfo) method).ReturnType;
+                       eclass = ExprClass.Value;
+                       
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       //
+                       // Invocation on delegates call the virtual Invoke member
+                       // so we are always `instance' calls
+                       //
+                       Invocation.EmitCall (ec, false, false, InstanceExpr, method, Arguments, loc);
+               }
+
+               public override void EmitStatement (EmitContext ec)
+               {
+                       Emit (ec);
+                       // 
+                       // Pop the return value if there is one
+                       //
+                       if (method is MethodInfo){
+                               if (((MethodInfo) method).ReturnType != TypeManager.void_type)
+                                       ec.ig.Emit (OpCodes.Pop);
+                       }
+               }
+
+       }
+}