2006-06-16 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / gmcs / delegate.cs
index c6a22440ddcf5a2a4fdd552150a9fd060b87f5a3..dd10369b7ec0644d1dff1d0e43840165e942a79d 100644 (file)
@@ -47,7 +47,7 @@ namespace Mono.CSharp {
                        Modifiers.UNSAFE |
                        Modifiers.PRIVATE;
 
-               public Delegate (NamespaceEntry ns, TypeContainer parent, Expression type,
+               public Delegate (NamespaceEntry ns, DeclSpace parent, Expression type,
                                 int mod_flags, MemberName name, Parameters param_list,
                                 Attributes attrs)
                        : base (ns, parent, name, attrs)
@@ -145,9 +145,6 @@ namespace Mono.CSharp {
 
                public override bool Define ()
                {
-                       MethodAttributes mattr;
-                       int i;
-
                        if (IsGeneric) {
                                foreach (TypeParameter type_param in TypeParameters)
                                        type_param.DefineType (this);
@@ -159,10 +156,10 @@ namespace Mono.CSharp {
                        const_arg_types [0] = TypeManager.object_type;
                        const_arg_types [1] = TypeManager.intptr_type;
 
-                       mattr = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName |
+                       const MethodAttributes ctor_mattr = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName |
                                MethodAttributes.HideBySig | MethodAttributes.Public;
 
-                       ConstructorBuilder = TypeBuilder.DefineConstructor (mattr,
+                       ConstructorBuilder = TypeBuilder.DefineConstructor (ctor_mattr,
                                                                            CallingConventions.Standard,
                                                                            const_arg_types);
 
@@ -211,11 +208,9 @@ namespace Mono.CSharp {
                        ReturnType = ReturnType.ResolveAsTypeTerminal (this, false);
                        if (ReturnType == null)
                                return false;
-                        
-                       ret_type = ReturnType.Type;
-                       if (ret_type == null)
-                               return false;
 
+                       ret_type = ReturnType.Type;
+            
                        if (!Parent.AsAccessible (ret_type, ModFlags)) {
                                Report.Error (58, Location,
                                              "Inconsistent accessibility: return type `" +
@@ -236,22 +231,13 @@ namespace Mono.CSharp {
                        
                        CallingConventions cc = Parameters.CallingConvention;
 
-                       mattr = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual;
+                       const MethodAttributes mattr = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.NewSlot;
 
                        InvokeBuilder = TypeBuilder.DefineMethod ("Invoke", 
                                                                  mattr,                     
                                                                  cc,
                                                                  ret_type,                  
                                                                  Parameters.Types);
-
-                       //
-                       // Define parameters, and count out/ref parameters
-                       //
-                       int out_params = 0;
-                       foreach (Parameter p in Parameters.FixedParameters) {
-                               if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0)
-                                       out_params++;
-                       }
                        
                        InvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
 
@@ -260,86 +246,64 @@ namespace Mono.CSharp {
                        //
                        // BeginInvoke
                        //
-                       int params_num = Parameters.Count;
-                       Type [] async_param_types = new Type [params_num + 2];
-
-                       Parameters.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 = Parameters.Count;
-                       Parameters.ApplyAttributes (BeginInvokeBuilder);
-                       BeginInvokeBuilder.DefineParameter (i + 1, ParameterAttributes.None, "callback");
-                       BeginInvokeBuilder.DefineParameter (i + 2, ParameterAttributes.None, "object");
+                       Parameters async_parameters = Parameters.MergeGenerated (Parameters, 
+                               new Parameter (TypeManager.asynccallback_type, "callback", Parameter.Modifier.NONE, null, Location),
+                               new Parameter (TypeManager.object_type, "object", Parameter.Modifier.NONE, null, Location));
                        
-                       BeginInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
+                       BeginInvokeBuilder = TypeBuilder.DefineMethod ("BeginInvoke",
+                               mattr, cc, TypeManager.iasyncresult_type, async_parameters.Types);
 
-                       Parameter [] async_params = new Parameter [params_num + 2];
-                       Parameters.FixedParameters.CopyTo (async_params, 0);
-                       
-                       async_params [params_num] = new Parameter (
-                               TypeManager.asynccallback_type, "callback",
-                                                                  Parameter.Modifier.NONE, null, Location);
-                       async_params [params_num + 1] = new Parameter (
-                               TypeManager.object_type, "object",
-                                                                  Parameter.Modifier.NONE, null, Location);
-
-                       Parameters async_parameters = new Parameters (async_params);
-                       async_parameters.Resolve (this);
+                       BeginInvokeBuilder.SetImplementationFlags (MethodImplAttributes.Runtime);
                        async_parameters.ApplyAttributes (BeginInvokeBuilder);
-
                        TypeManager.RegisterMethod (BeginInvokeBuilder, async_parameters);
 
                        //
                        // 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++){
+
+                       //
+                       // Define parameters, and count out/ref parameters
+                       //
+                       Parameters end_parameters;
+                       int out_params = 0;
+
+                       foreach (Parameter p in Parameters.FixedParameters) {
+                               if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0)
+                                       ++out_params;
+                       }
+
+                       if (out_params > 0) {
+                               Type [] end_param_types = new Type [out_params];
+                               Parameter [] end_params = new Parameter [out_params ];
+
+                               int param = 0; 
+                               for (int i = 0; i < Parameters.FixedParameters.Length; ++i) {
                                        Parameter p = Parameters.FixedParameters [i];
                                        if ((p.ModFlags & Parameter.Modifier.ISBYREF) == 0)
                                                continue;
 
-                                       end_param_types [param] = Parameters.Types [i];
+                                       end_param_types [param] = p.ExternalType();
                                        end_params [param] = p;
-                                       param++;
+                                       ++param;
                                }
+                               end_parameters = new Parameters (end_params, end_param_types);
+                       }
+                       else {
+                               end_parameters = Parameters.EmptyReadOnlyParameters;
                        }
-                       end_param_types [out_params] = TypeManager.iasyncresult_type;
-                       end_params [out_params] = new Parameter (TypeManager.system_iasyncresult_expr, "result", Parameter.Modifier.NONE, null, Location);
 
+                       end_parameters = Parameters.MergeGenerated (end_parameters,
+                               new Parameter (TypeManager.iasyncresult_type, "result", Parameter.Modifier.NONE, null, Location));
+                       
                        //
                        // Create method, define parameters, register parameters with type system
                        //
-                       EndInvokeBuilder = TypeBuilder.DefineMethod ("EndInvoke", mattr, cc, ret_type, end_param_types);
+                       EndInvokeBuilder = TypeBuilder.DefineMethod ("EndInvoke", mattr, cc, ret_type, end_parameters.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);
-                       end_parameters.Resolve (this);
-
+                       end_parameters.ApplyAttributes (EndInvokeBuilder);
                        TypeManager.RegisterMethod (EndInvokeBuilder, end_parameters);
 
                        return true;
@@ -484,7 +448,7 @@ namespace Mono.CSharp {
                                arg_count = args.Count;
 
                        Expression ml = Expression.MemberLookup (
-                               ec, delegate_type, "Invoke", loc);
+                               ec.ContainerType, delegate_type, "Invoke", loc);
 
                        MethodGroupExpr me = ml as MethodGroupExpr;
                        if (me == null) {
@@ -521,10 +485,10 @@ namespace Mono.CSharp {
                ///  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)
+               public static bool VerifyDelegate (EmitContext ec, Type delegate_type, Location loc)
                {
                        Expression ml = Expression.MemberLookup (
-                               ec, delegate_type, "Invoke", loc);
+                               ec.ContainerType, delegate_type, "Invoke", loc);
                        
                        if (!(ml is MethodGroupExpr)) {
                                Report.Error (-100, loc, "Internal error: could not find Invoke method!");
@@ -535,7 +499,7 @@ namespace Mono.CSharp {
                        ParameterData pd = TypeManager.GetParameterData (mb);
 
                        Expression probe_ml = Expression.MemberLookup (
-                               ec, delegate_type, "Invoke", loc);
+                               ec.ContainerType, delegate_type, "Invoke", loc);
                        
                        if (!(probe_ml is MethodGroupExpr)) {
                                Report.Error (-100, loc, "Internal error: could not find Invoke method!");
@@ -653,7 +617,7 @@ namespace Mono.CSharp {
                protected MethodGroupExpr method_group;
                protected Expression delegate_instance_expression;
 
-               public DelegateCreation () {}
+               protected DelegateCreation () {}
 
                public static void Error_NoMatchingMethodForDelegate (EmitContext ec, MethodGroupExpr mg, Type type, Location loc)
                {
@@ -704,7 +668,7 @@ namespace Mono.CSharp {
                protected bool ResolveConstructorMethod (EmitContext ec)
                {
                        Expression ml = Expression.MemberLookup (
-                               ec, type, ".ctor", loc);
+                               ec.ContainerType, type, ".ctor", loc);
 
                        if (!(ml is MethodGroupExpr)) {
                                Report.Error (-100, loc, "Internal error: Could not find delegate constructor!");
@@ -725,19 +689,12 @@ namespace Mono.CSharp {
                        return null;
                }
 
-               protected Expression ResolveMethodGroupExpr (EmitContext ec, MethodGroupExpr mg,
-                                                            bool check_only)
+               protected Expression ResolveMethodGroupExpr (EmitContext ec, MethodGroupExpr mg)
                {
-                       foreach (MethodInfo mi in mg.Methods){
-                               delegate_method  = Delegate.VerifyMethod (ec.ContainerType, type, mg, mi, loc);
-                               
-                               if (delegate_method != null)
-                                       break;
-                       }
-                       
+                       delegate_method = ImplicitStandardConversionExists (mg, type);
+
                        if (delegate_method == null) {
-                               if (!check_only)
-                                       Error_NoMatchingMethodForDelegate (ec, mg, type, loc);
+                               Error_NoMatchingMethodForDelegate (ec, mg, type, loc);
                                return null;
                        }
                        
@@ -812,13 +769,13 @@ namespace Mono.CSharp {
                }
 
                static public Expression Create (EmitContext ec, MethodGroupExpr mge,
-                                                Type target_type, bool check_only, Location loc)
+                                                Type target_type, Location loc)
                {
                        ImplicitDelegateCreation d = new ImplicitDelegateCreation (target_type, loc);
-                       if (d.ResolveConstructorMethod (ec))
-                               return d.ResolveMethodGroupExpr (ec, mge, check_only);
-                       else
+                       if (!d.ResolveConstructorMethod (ec))
                                return null;
+
+                       return d.ResolveMethodGroupExpr (ec, mge);
                }
        }
        
@@ -851,21 +808,19 @@ namespace Mono.CSharp {
 
                        Argument a = (Argument) Arguments [0];
                        
-                       if (!a.ResolveMethodGroup (ec, loc))
+                       if (!a.ResolveMethodGroup (ec))
                                return null;
                        
                        Expression e = a.Expr;
 
                        if (e is AnonymousMethod && RootContext.Version != LanguageVersion.ISO_1)
-                               return ((AnonymousMethod) e).Compatible (ec, type, false);
+                               return ((AnonymousMethod) e).Compatible (ec, type);
 
                        MethodGroupExpr mg = e as MethodGroupExpr;
                        if (mg != null)
-                               return ResolveMethodGroupExpr (ec, mg, false);
-
-                       Type e_type = e.Type;
+                               return ResolveMethodGroupExpr (ec, mg);
 
-                       if (!TypeManager.IsDelegateType (e_type)) {
+                       if (!TypeManager.IsDelegateType (e.Type)) {
                                Report.Error (149, loc, "Method name expected");
                                return null;
                        }
@@ -881,8 +836,8 @@ namespace Mono.CSharp {
 
                        // 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 + "' " +
+                       if (!Delegate.VerifyDelegate (ec, type, loc)) {
+                               Report.Error (29, loc, "Cannot implicitly convert type '" + e.Type + "' " +
                                              "to type '" + type + "'");
                                return null;
                        }
@@ -950,7 +905,7 @@ namespace Mono.CSharp {
                        if (!Delegate.VerifyApplicability (ec, del_type, Arguments, loc))
                                return null;
 
-                       Expression lookup = Expression.MemberLookup (ec, del_type, "Invoke", loc);
+                       Expression lookup = Expression.MemberLookup (ec.ContainerType, del_type, "Invoke", loc);
                        if (!(lookup is MethodGroupExpr)) {
                                Report.Error (-100, loc, "Internal error: could not find Invoke method!");
                                return null;