2007-08-18 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / parameter.cs
index 01919e6249215ecbb521eca640442a3cda71d2ab..a8d6b6f7d3ef553a6a45209fd45b198fa04c48c8 100644 (file)
@@ -2,6 +2,7 @@
 // parameter.cs: Parameter definition.
 //
 // Author: Miguel de Icaza (miguel@gnu.org)
+//         Marek Safar (marek.safar@seznam.cz)
 //
 // Licensed under the terms of the GNU GPL
 //
@@ -23,12 +24,10 @@ namespace Mono.CSharp {
        public abstract class ParameterBase : Attributable {
 
                protected ParameterBuilder builder;
-               public readonly Location Location;
 
-               public ParameterBase (Attributes attrs, Location loc)
+               protected ParameterBase (Attributes attrs)
                        : base (attrs)
                {
-                       Location = loc;
                }
 
                public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
@@ -49,7 +48,7 @@ namespace Mono.CSharp {
                        builder.SetCustomAttribute (cb);
                }
 
-               public override bool IsClsCompliaceRequired(DeclSpace ds)
+               public override bool IsClsComplianceRequired()
                {
                        return false;
                }
@@ -58,15 +57,15 @@ namespace Mono.CSharp {
        /// <summary>
        /// Class for applying custom attributes on the return type
        /// </summary>
-       public class ReturnParameter: ParameterBase {
+       public class ReturnParameter : ParameterBase {
                public ReturnParameter (MethodBuilder mb, Location location):
-                       base (null, location)
+                       base (null)
                {
                        try {
                                builder = mb.DefineParameter (0, ParameterAttributes.None, "");                 
                        }
                        catch (ArgumentOutOfRangeException) {
-                               Report.Warning (-24, location, "The Microsoft .NET Runtime 1.x does not permit setting custom attributes on the return type");
+                               Report.RuntimeMissingSupport (location, "custom attributes on the return type");
                        }
                }
 
@@ -89,6 +88,12 @@ namespace Mono.CSharp {
                        }
                }
 
+               public override IResolveContext ResolveContext {
+                       get {
+                               throw new NotSupportedException ();
+                       }
+               }
+
                /// <summary>
                /// Is never called
                /// </summary>
@@ -103,9 +108,11 @@ namespace Mono.CSharp {
        /// Class for applying custom attributes on the implicit parameter type
        /// of the 'set' method in properties, and the 'add' and 'remove' methods in events.
        /// </summary>
-       public class ImplicitParameter: ParameterBase {
-               public ImplicitParameter (MethodBuilder mb, Location loc):
-                       base (null, loc)
+       /// 
+       // TODO: should use more code from Parameter.ApplyAttributeBuilder
+       public class ImplicitParameter : ParameterBase {
+               public ImplicitParameter (MethodBuilder mb):
+                       base (null)
                {
                        builder = mb.DefineParameter (1, ParameterAttributes.None, "");                 
                }
@@ -116,6 +123,12 @@ namespace Mono.CSharp {
                        }
                }
 
+               public override IResolveContext ResolveContext {
+                       get {
+                               throw new NotSupportedException ();
+                       }
+               }
+
                /// <summary>
                /// Is never called
                /// </summary>
@@ -126,6 +139,74 @@ namespace Mono.CSharp {
                }
        }
 
+       public class ImplicitLambdaParameter : Parameter
+       {
+               public ImplicitLambdaParameter (string name, Location loc)
+                       : base ((Type)null, name, Modifier.NONE, null, loc)
+               {
+               }
+
+               public override bool Resolve (IResolveContext ec)
+               {
+                       if (parameter_type == null)
+                               throw new InternalErrorException ("Implicit lambda parameter type is not set");
+
+                       return true;
+               }
+       }
+
+       public class ParamsParameter : Parameter {
+               public ParamsParameter (Expression type, string name, Attributes attrs, Location loc):
+                       base (type, name, Parameter.Modifier.PARAMS, attrs, loc)
+               {
+               }
+
+               public override bool Resolve (IResolveContext ec)
+               {
+                       if (!base.Resolve (ec))
+                               return false;
+
+                       if (!parameter_type.IsArray || parameter_type.GetArrayRank () != 1) {
+                               Report.Error (225, Location, "The params parameter must be a single dimensional array");
+                               return false;
+                       }
+                       return true;
+               }
+
+               public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
+               {
+                       base.ApplyAttributes (mb, cb, index);
+
+                       CustomAttributeBuilder a = new CustomAttributeBuilder (
+                               TypeManager.cons_param_array_attribute, new object[0]);
+                               
+                       builder.SetCustomAttribute (a);
+               }
+       }
+
+       public class ArglistParameter : Parameter {
+               // Doesn't have proper type because it's never chosen for better conversion
+               public ArglistParameter () :
+                       base (typeof (ArglistParameter), String.Empty, Parameter.Modifier.ARGLIST, null, Location.Null)
+               {
+               }
+
+               public override bool CheckAccessibility (InterfaceMemberBase member)
+               {
+                       return true;
+               }
+
+               public override bool Resolve (IResolveContext ec)
+               {
+                       return true;
+               }
+
+               public override string GetSignatureForError ()
+               {
+                       return "__arglist";
+               }
+       }
+
        /// <summary>
        ///   Represents a single method parameter
        /// </summary>
@@ -133,34 +214,69 @@ namespace Mono.CSharp {
                [Flags]
                public enum Modifier : byte {
                        NONE    = 0,
-                       REF     = 1,
-                       OUT     = 2,
+                       REF     = REFMASK | ISBYREF,
+                       OUT     = OUTMASK | ISBYREF,
                        PARAMS  = 4,
                        // This is a flag which says that it's either REF or OUT.
                        ISBYREF = 8,
-                       ARGLIST = 16
+                       ARGLIST = 16,
+                       REFMASK = 32,
+                       OUTMASK = 64,
+                       This    = 128
                }
 
                static string[] attribute_targets = new string [] { "param" };
 
-               public Expression TypeName;
-               public readonly Modifier ModFlags;
-               public readonly string Name;
-               Type parameter_type;
+               Expression TypeName;
+               public Modifier modFlags;
+               public string Name;
+               public bool IsCaptured;
+               protected Type parameter_type;
+               public readonly Location Location;
 
-               EmitContext ec;  // because ApplyAtrribute doesn't have ec
+               IResolveContext resolve_context;
+
+               Variable var;
+               public Variable Variable {
+                       get { return var; }
+               }
+
+#if GMCS_SOURCE
+               public bool IsTypeParameter;
+               GenericConstraints constraints;
+#else
+               public bool IsTypeParameter {
+                       get {
+                               return false;
+                       }
+                       set {
+                               if (value)
+                                       throw new Exception ("You can not se TypeParameter in MCS");
+                       }
+               }
+#endif
                
                public Parameter (Expression type, string name, Modifier mod, Attributes attrs, Location loc)
-                       : base (attrs, loc)
+                       : this (type.Type, name, mod, attrs, loc)
                {
-                       Name = name;
-                       ModFlags = mod;
+                       if (type == TypeManager.system_void_expr)
+                               Report.Error (1536, loc, "Invalid parameter type `void'");
+                       
                        TypeName = type;
                }
 
+               public Parameter (Type type, string name, Modifier mod, Attributes attrs, Location loc)
+                       : base (attrs)
+               {
+                       Name = name;
+                       modFlags = mod;
+                       parameter_type = type;
+                       Location = loc;
+               }
+
                public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
                {
-                       if (a.Type == TypeManager.in_attribute_type && Attributes == ParameterAttributes.Out) {
+                       if (a.Type == TypeManager.in_attribute_type && ModFlags == Modifier.OUT) {
                                Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute");
                                return;
                        }
@@ -170,8 +286,8 @@ namespace Mono.CSharp {
                                return;
                        }
 
-                       if (a.Type == TypeManager.out_attribute_type && (ModFlags & Modifier.REF) != 0 &&
-                           !OptAttributes.Contains (TypeManager.in_attribute_type, ec)) {
+                       if (a.Type == TypeManager.out_attribute_type && (ModFlags & Modifier.REF) == Modifier.REF &&
+                           !OptAttributes.Contains (TypeManager.in_attribute_type)) {
                                Report.Error (662, a.Location,
                                        "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither");
                                return;
@@ -181,33 +297,85 @@ namespace Mono.CSharp {
                                Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead");
                        }
 
+                       // TypeManager.default_parameter_value_attribute_type is null if !NET_2_0, or if System.dll is not referenced
+                       if (a.Type == TypeManager.default_parameter_value_attribute_type) {
+                               object val = a.GetParameterDefaultValue ();
+                               if (val != null) {
+                                       Type t = val.GetType ();
+                                       if (t.IsArray || TypeManager.IsSubclassOf (t, TypeManager.type_type)) {
+                                               if (parameter_type == TypeManager.object_type) {
+                                                       if (!t.IsArray)
+                                                               t = TypeManager.type_type;
+
+                                                       Report.Error (1910, a.Location, "Argument of type `{0}' is not applicable for the DefaultValue attribute",
+                                                               TypeManager.CSharpName (t));
+                                               } else {
+                                                       Report.Error (1909, a.Location, "The DefaultValue attribute is not applicable on parameters of type `{0}'",
+                                                               TypeManager.CSharpName (parameter_type)); ;
+                                               }
+                                               return;
+                                       }
+                               }
+
+                               if (parameter_type == TypeManager.object_type ||
+                                   (val == null && !TypeManager.IsValueType (parameter_type)) ||
+                                   (val != null && TypeManager.TypeToCoreType (val.GetType ()) == parameter_type))
+                                       builder.SetConstant (val);
+                               else
+                                       Report.Error (1908, a.Location, "The type of the default value should match the type of the parameter");
+                               return;
+                       }
+
                        base.ApplyAttributeBuilder (a, cb);
                }
+               
+               public virtual bool CheckAccessibility (InterfaceMemberBase member)
+               {
+                       if (IsTypeParameter)
+                               return true;
+
+                       return member.ds.AsAccessible (parameter_type, member.ModFlags);
+               }
+
+               public override IResolveContext ResolveContext {
+                       get {
+                               return resolve_context;
+                       }
+               }
 
                // <summary>
                //   Resolve is used in method definitions
                // </summary>
-               public bool Resolve (EmitContext ec)
+               public virtual bool Resolve (IResolveContext ec)
                {
-                       this.ec = ec;
+                       // HACK: to resolve attributes correctly
+                       this.resolve_context = ec;
+
+                       if (parameter_type != null)
+                               return true;
 
                        TypeExpr texpr = TypeName.ResolveAsTypeTerminal (ec, false);
                        if (texpr == null)
                                return false;
 
-                       parameter_type = texpr.ResolveType (ec);
-                       
-                       if (parameter_type.IsAbstract && parameter_type.IsSealed) {
-                               Report.Error (721, Location, "`{0}': static types cannot be used as parameters", GetSignatureForError ());
-                               return false;
+                       parameter_type = texpr.Type;
+
+#if GMCS_SOURCE
+                       TypeParameterExpr tparam = texpr as TypeParameterExpr;
+                       if (tparam != null) {
+                               IsTypeParameter = true;
+                               constraints = tparam.TypeParameter.Constraints;
+                               return true;
                        }
+#endif
 
-                       if (parameter_type == TypeManager.void_type){
-                               Report.Error (1536, Location, "Invalid parameter type 'void'");
+                       if ((parameter_type.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
+                               Report.Error (721, Location, "`{0}': static types cannot be used as parameters", 
+                                       texpr.GetSignatureForError ());
                                return false;
                        }
 
-                       if ((ModFlags & Parameter.Modifier.ISBYREF) != 0){
+                       if ((modFlags & Parameter.Modifier.ISBYREF) != 0){
                                if (parameter_type == TypeManager.typed_reference_type ||
                                    parameter_type == TypeManager.arg_iterator_type){
                                        Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'",
@@ -215,82 +383,107 @@ namespace Mono.CSharp {
                                        return false;
                                }
                        }
+
+                       if ((modFlags & Modifier.This) != 0 && parameter_type.IsPointer) {
+                               Report.Error (1103, Location, "The type of extension method cannot be `{0}'",
+                                       TypeManager.CSharpName (parameter_type));
+                               return false;
+                       }
                        
-                       return parameter_type != null;
+                       return true;
+               }
+
+               public void ResolveVariable (ToplevelBlock toplevel, int idx)
+               {
+                       if (toplevel.RootScope != null)
+                               var = toplevel.RootScope.GetCapturedParameter (this);
+                       if (var == null)
+                               var = new ParameterVariable (this, idx);
                }
 
                public Type ExternalType ()
                {
-                       if ((ModFlags & Parameter.Modifier.ISBYREF) != 0)
+                       if ((modFlags & Parameter.Modifier.ISBYREF) != 0)
                                return TypeManager.GetReferenceType (parameter_type);
                        
                        return parameter_type;
                }
 
+               public bool HasExtensionMethodModifier {
+                       get { return (modFlags & Modifier.This) != 0; }
+               }
+
+               public Modifier ModFlags {
+                       get { return modFlags & ~Modifier.This; }
+               }
+
                public Type ParameterType {
                        get {
                                return parameter_type;
                        }
+                       set {
+                               parameter_type = value;
+                               IsTypeParameter = false;
+                       }
                }
-               
-               public ParameterAttributes Attributes {
+
+#if GMCS_SOURCE
+               public GenericConstraints GenericConstraints {
                        get {
-                               int flags = ((int) ModFlags) & ~((int) Parameter.Modifier.ISBYREF);
-                               switch ((Modifier) flags) {
-                               case Modifier.NONE:
-                                       return ParameterAttributes.None;
-                               case Modifier.REF:
-                                       return ParameterAttributes.None;
-                               case Modifier.OUT:
-                                       return ParameterAttributes.Out;
-                               case Modifier.PARAMS:
-                                       return 0;
-                               }
-                               
-                               return ParameterAttributes.None;
+                               return constraints;
                        }
                }
-               
-               public override AttributeTargets AttributeTargets {
+#endif
+
+               ParameterAttributes Attributes {
                        get {
-                               return AttributeTargets.Parameter;
+                               return (modFlags & Modifier.OUT) == Modifier.OUT ?
+                                       ParameterAttributes.Out : ParameterAttributes.None;
                        }
                }
 
-               /// <summary>
-               ///   Returns the signature for this parameter evaluating it on the
-               ///   @tc context
-               /// </summary>
-               public string GetSignature (EmitContext ec)
+               // TODO: should be removed !!!!!!!
+               public static ParameterAttributes GetParameterAttributes (Modifier mod)
                {
-                       if (parameter_type == null){
-                               if (!Resolve (ec))
-                                       return null;
+                       int flags = ((int) mod) & ~((int) Parameter.Modifier.ISBYREF);
+                       switch ((Modifier) flags) {
+                       case Modifier.NONE:
+                               return ParameterAttributes.None;
+                       case Modifier.REF:
+                               return ParameterAttributes.None;
+                       case Modifier.OUT:
+                               return ParameterAttributes.Out;
+                       case Modifier.PARAMS:
+                               return 0;
+                       }
+                               
+                       return ParameterAttributes.None;
+               }
+               
+               public override AttributeTargets AttributeTargets {
+                       get {
+                               return AttributeTargets.Parameter;
                        }
-
-                       return ExternalType ().FullName;
                }
 
-               public string GetSignatureForError ()
+               public virtual string GetSignatureForError ()
                {
                        string type_name;
                        if (parameter_type != null)
                                type_name = TypeManager.CSharpName (parameter_type);
-                       else if (TypeName.Type != null)
-                               type_name = TypeManager.CSharpName (TypeName.Type);
                        else
-                               type_name = TypeName.ToString ();
+                               type_name = TypeName.GetSignatureForError ();
 
-                       string mod = GetModifierSignature (ModFlags);
+                       string mod = GetModifierSignature (modFlags);
                        if (mod.Length > 0)
-                               return String.Concat (mod, " ", type_name);
+                               return String.Concat (mod, ' ', type_name);
 
                        return type_name;
                }
 
                public static string GetModifierSignature (Modifier mod)
                {
-                       switch (mod & unchecked (~Modifier.ISBYREF)) {
+                       switch (mod) {
                                case Modifier.OUT:
                                        return "out";
                                case Modifier.PARAMS:
@@ -299,23 +492,33 @@ namespace Mono.CSharp {
                                        return "ref";
                                case Modifier.ARGLIST:
                                        return "__arglist";
+                               case Modifier.This:
+                                       return "this";
                                default:
                                        return "";
                        }
                }
 
-               public void DefineParameter (EmitContext ec, MethodBuilder mb, ConstructorBuilder cb, int index)
+               public void IsClsCompliant ()
                {
-                       ParameterAttributes par_attr = Attributes;
-                                       
+                       if (AttributeTester.IsClsCompliant (ExternalType ()))
+                               return;
+
+                       Report.Error (3001, Location, "Argument type `{0}' is not CLS-compliant", GetSignatureForError ());
+               }
+
+               public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
+               {
+#if !GMCS_SOURCE || !MS_COMPATIBLE
+                       // TODO: It should use mb.DefineGenericParameters
                        if (mb == null)
-                               builder = cb.DefineParameter (index, par_attr, Name);
+                               builder = cb.DefineParameter (index, Attributes, Name);
                        else 
-                               builder = mb.DefineParameter (index, par_attr, Name);
-                                       
-                       if (OptAttributes != null) {
-                               OptAttributes.Emit (ec, this);
-                       }
+                               builder = mb.DefineParameter (index, Attributes, Name);
+#endif
+
+                       if (OptAttributes != null)
+                               OptAttributes.Emit ();
                }
 
                public override string[] ValidAttributeTargets {
@@ -323,116 +526,221 @@ namespace Mono.CSharp {
                                return attribute_targets;
                        }
                }
+
+               protected class ParameterVariable : Variable
+               {
+                       public readonly Parameter Parameter;
+                       public readonly int Idx;
+                       public readonly bool IsRef;
+
+                       public ParameterVariable (Parameter par, int idx)
+                       {
+                               this.Parameter = par;
+                               this.Idx = idx;
+                               this.IsRef = (par.ModFlags & Parameter.Modifier.ISBYREF) != 0;
+                       }
+
+                       public override Type Type {
+                               get { return Parameter.ParameterType; }
+                       }
+
+                       public override bool HasInstance {
+                               get { return false; }
+                       }
+
+                       public override bool NeedsTemporary {
+                               get { return false; }
+                       }
+
+                       public override void EmitInstance (EmitContext ec)
+                       {
+                       }
+
+                       public override void Emit (EmitContext ec)
+                       {
+                               int arg_idx = Idx;
+                               if (!ec.MethodIsStatic)
+                                       arg_idx++;
+
+                               ParameterReference.EmitLdArg (ec.ig, arg_idx);
+                       }
+
+                       public override void EmitAssign (EmitContext ec)
+                       {
+                               int arg_idx = Idx;
+                               if (!ec.MethodIsStatic)
+                                       arg_idx++;
+
+                               if (arg_idx <= 255)
+                                       ec.ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
+                               else
+                                       ec.ig.Emit (OpCodes.Starg, arg_idx);
+                       }
+
+                       public override void EmitAddressOf (EmitContext ec)
+                       {
+                               int arg_idx = Idx;
+
+                               if (!ec.MethodIsStatic)
+                                       arg_idx++;
+
+                               if (IsRef) {
+                                       if (arg_idx <= 255)
+                                               ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
+                                       else
+                                               ec.ig.Emit (OpCodes.Ldarg, arg_idx);
+                               } else {
+                                       if (arg_idx <= 255)
+                                               ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
+                                       else
+                                               ec.ig.Emit (OpCodes.Ldarga, arg_idx);
+                               }
+                       }
+               }
+
+               public Parameter Clone ()
+               {
+                       Parameter p = new Parameter (parameter_type, Name, ModFlags, attributes, Location);
+                       p.IsTypeParameter = IsTypeParameter;
+
+                       return p;
+               }
        }
 
        /// <summary>
        ///   Represents the methods parameters
        /// </summary>
-       public class Parameters {
+       public class Parameters : ParameterData {
+               // Null object pattern
                public Parameter [] FixedParameters;
-               public readonly Parameter ArrayParameter;
                public readonly bool HasArglist;
-               string signature;
                Type [] types;
+               int count;
+
+               public static readonly Parameters EmptyReadOnlyParameters = new Parameters ();
+               static readonly Parameter ArgList = new ArglistParameter ();
+
+#if GMCS_SOURCE
+//             public readonly TypeParameter[] TypeParameters;
+#endif
+
+               private Parameters ()
+               {
+                       FixedParameters = new Parameter[0];
+                       types = new Type [0];
+               }
+
+               private Parameters (Parameter[] parameters, Type[] types)
+               {
+                       FixedParameters = parameters;
+                       this.types = types;
+                       count = types.Length;
+               }
                
-               static Parameters empty_parameters;
-               
-               public Parameters (Parameter [] fixed_parameters, Parameter array_parameter)
+               public Parameters (params Parameter[] parameters)
                {
-                       FixedParameters = fixed_parameters;
-                       ArrayParameter  = array_parameter;
+                       if (parameters == null)
+                               throw new ArgumentException ("Use EmptyReadOnlyPatameters");
+
+                       FixedParameters = parameters;
+                       count = parameters.Length;
                }
 
-               public Parameters (Parameter [] fixed_parameters, bool has_arglist)
+               public Parameters (Parameter[] parameters, bool has_arglist):
+                       this (parameters)
                {
-                       FixedParameters = fixed_parameters;
                        HasArglist = has_arglist;
                }
+               
+               public static Parameters CreateFullyResolved (Parameter p)
+               {
+                       return new Parameters (new Parameter [] { p }, new Type [] { p.ParameterType });
+               }
+               
+               public static Parameters CreateFullyResolved (Parameter[] parameters, Type[] types)
+               {
+                       return new Parameters (parameters, types);
+               }
 
                /// <summary>
-               ///   This is used to reuse a set of empty parameters, because they
-               ///   are common
+               /// Use this method when you merge compiler generated argument with user arguments
                /// </summary>
-               public static Parameters EmptyReadOnlyParameters {
-                       get {
-                               if (empty_parameters == null)
-                                       empty_parameters = new Parameters (null, null);
-                       
-                               return empty_parameters;
+               public static Parameters MergeGenerated (Parameters userParams, params Parameter[] compilerParams)
+               {
+                       Parameter[] all_params = new Parameter [userParams.count + compilerParams.Length];
+                       Type[] all_types = new Type[all_params.Length];
+                       userParams.FixedParameters.CopyTo(all_params, 0);
+                       userParams.Types.CopyTo (all_types, 0);
+
+                       int last_filled = userParams.Count;
+                       foreach (Parameter p in compilerParams) {
+                               for (int i = 0; i < last_filled; ++i) {
+                                       while (p.Name == all_params [i].Name) {
+                                               p.Name = '_' + p.Name;
+                                       }
+                               }
+                               all_params [last_filled] = p;
+                               all_types [last_filled] = p.ParameterType;
+                               ++last_filled;
                        }
+                       
+                       return new Parameters (all_params, all_types);
                }
-               
+
                public bool Empty {
                        get {
-                               return (FixedParameters == null) && (ArrayParameter == null);
+                               return count == 0;
                        }
                }
 
-               public void ComputeSignature (EmitContext ec)
-               {
-                       signature = "";
-                       if (FixedParameters != null){
-                               for (int i = 0; i < FixedParameters.Length; i++){
-                                       Parameter par = FixedParameters [i];
-                                       
-                                       signature += par.GetSignature (ec);
-                               }
+               public int Count {
+                       get {
+                               return HasArglist ? count + 1 : count;
                        }
-                       //
-                       // Note: as per the spec, the `params' arguments (ArrayParameter)
-                       // are not used in the signature computation for a method
-                       //
                }
 
-               void Error_DuplicateParameterName (string name, Location loc)
-               {
-                       Report.Error (
-                               100, loc, "The parameter name `" + name + "' is a duplicate");
+               //
+               // The property can be used after parameter types were resolved.
+               //
+               public Type ExtensionMethodType {
+                       get {
+                               if (count == 0)
+                                       return null;
+
+                               return FixedParameters [0].HasExtensionMethodModifier ?
+                                       types [0] : null;
+                       }
                }
-               
-               public bool VerifyArgs ()
-               {
-                       int count;
-                       int i, j;
 
-                       if (FixedParameters == null)
+               public bool HasExtensionMethodType {
+                       get {
+                               if (count == 0)
+                                       return false;
+
+                               return FixedParameters [0].HasExtensionMethodModifier;
+                       }
+               }
+
+
+               bool VerifyArgs ()
+               {
+                       if (count < 2)
                                return true;
-                       
-                       count = FixedParameters.Length;
-                       string array_par_name = ArrayParameter != null ? ArrayParameter.Name : null;
 
-                       for (i = 0; i < count; i++){
+                       for (int i = 0; i < count; i++){
                                string base_name = FixedParameters [i].Name;
-                               for (j = i + 1; j < count; j++){
+                               for (int j = i + 1; j < count; j++){
                                        if (base_name != FixedParameters [j].Name)
                                                continue;
-                                       Error_DuplicateParameterName (base_name,
-                                               FixedParameters [i].Location);
-                                       return false;
-                               }
 
-                               if (base_name == array_par_name){
-                                       Error_DuplicateParameterName (base_name,
-                                               FixedParameters [i].Location);
+                                       Report.Error (100, FixedParameters [i].Location,
+                                               "The parameter name `{0}' is a duplicate", base_name);
                                        return false;
                                }
                        }
                        return true;
                }
                
-               /// <summary>
-               ///    Returns the signature of the Parameters evaluated in
-               ///    the @ec EmitContext
-               /// </summary>
-               public string GetSignature (EmitContext ec)
-               {
-                       if (signature == null){
-                               VerifyArgs ();
-                               ComputeSignature (ec);
-                       }
-                       
-                       return signature;
-               }
                
                /// <summary>
                ///    Returns the paramenter information based on the name
@@ -440,25 +748,19 @@ namespace Mono.CSharp {
                public Parameter GetParameterByName (string name, out int idx)
                {
                        idx = 0;
-                       int i = 0;
 
-                       if (FixedParameters != null){
-                               foreach (Parameter par in FixedParameters){
-                                       if (par.Name == name){
-                                               idx = i;
-                                               return par;
-                                       }
-                                       i++;
-                               }
-                       }
+                       if (count == 0)
+                               return null;
+
+                       int i = 0;
 
-                       if (ArrayParameter != null){
-                               if (name == ArrayParameter.Name){
+                       foreach (Parameter par in FixedParameters){
+                               if (par.Name == name){
                                        idx = i;
-                                       return ArrayParameter;
+                                       return par;
                                }
+                               i++;
                        }
-                       
                        return null;
                }
 
@@ -469,179 +771,195 @@ namespace Mono.CSharp {
                        return GetParameterByName (name, out idx);
                }
                
-               bool ComputeParameterTypes (EmitContext ec)
+               public bool Resolve (IResolveContext ec)
                {
-                       int extra = (ArrayParameter != null) ? 1 : 0;
-                       int i = 0;
-                       int pc;
-
-                       if (FixedParameters == null)
-                               pc = extra;
-                       else
-                               pc = extra + FixedParameters.Length;
+                       if (types != null)
+                               return true;
 
-                       types = new Type [pc];
+                       types = new Type [count];
                        
-                       if (!VerifyArgs ()){
-                               FixedParameters = null;
+                       if (!VerifyArgs ())
                                return false;
-                       }
 
-                       bool failed = false;
-                       if (FixedParameters != null){
-                               foreach (Parameter p in FixedParameters){
-                                       Type t = null;
-                                       
-                                       if (p.Resolve (ec))
-                                               t = p.ExternalType ();
-                                       else
-                                               failed = true;
-
-                                       types [i] = t;
-                                       i++;
+                       bool ok = true;
+                       Parameter p;
+                       for (int i = 0; i < FixedParameters.Length; ++i) {
+                               p = FixedParameters [i];
+                               if (!p.Resolve (ec)) {
+                                       ok = false;
+                                       continue;
                                }
-                       }
-                       
-                       if (extra > 0){
-                               if (ArrayParameter.Resolve (ec))
-                                       types [i] = ArrayParameter.ExternalType ();
-                               else 
-                                       failed = true;
+                               types [i] = p.ExternalType ();
                        }
 
-                       if (failed){
-                               types = null;
-                               return false;
-                       }
-
-                       return true;
+                       return ok;
                }
-               
-               /// <summary>
-               ///   Returns the argument types as an array
-               /// </summary>
-               static Type [] no_types = new Type [0];
-               
-               public Type [] GetParameterInfo (EmitContext ec)
-               {
-                       if (types != null)
-                               return types;
-                       
-                       if (FixedParameters == null && ArrayParameter == null)
-                               return no_types;
 
-                       if (ComputeParameterTypes (ec) == false){
-                               types = null;
-                               return null;
+               public void ResolveVariable (ToplevelBlock toplevel)
+               {
+                       for (int i = 0; i < FixedParameters.Length; ++i) {
+                               Parameter p = FixedParameters [i];
+                               p.ResolveVariable (toplevel, i);
                        }
-
-                       return types;
                }
 
-               /// <summary>
-               ///   Returns the type of a given parameter, and stores in the `is_out'
-               ///   boolean whether this is an out or ref parameter.
-               ///
-               ///   Note that the returned type will not contain any dereference in this
-               ///   case (ie, you get "int" for a ref int instead of "int&"
-               /// </summary>
-               public Type GetParameterInfo (EmitContext ec, int idx, out Parameter.Modifier mod)
+               public CallingConventions CallingConvention
                {
-                       mod = Parameter.Modifier.NONE;
-                       
-                       if (!VerifyArgs ()){
-                               FixedParameters = null;
-                               return null;
+                       get {
+                               if (HasArglist)
+                                       return CallingConventions.VarArgs;
+                               else
+                                       return CallingConventions.Standard;
                        }
+               }
 
-                       if (FixedParameters == null && ArrayParameter == null)
-                               return null;
-                       
-                       if (types == null)
-                               if (ComputeParameterTypes (ec) == false)
-                                       return null;
-
-                       //
-                       // If this is a request for the variable lenght arg.
-                       //
-                       int array_idx = (FixedParameters != null ? FixedParameters.Length : 0);
-                       if (idx == array_idx)
-                               return types [idx];
-
-                       //
-                       // Otherwise, it is a fixed parameter
-                       //
-                       Parameter p = FixedParameters [idx];
-                       mod = p.ModFlags;
+               // Define each type attribute (in/out/ref) and
+               // the argument names.
+               public void ApplyAttributes (MethodBase builder)
+               {
+                       if (count == 0)
+                               return;
 
-                       if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0)
-                               mod |= Parameter.Modifier.ISBYREF;
+                       MethodBuilder mb = builder as MethodBuilder;
+                       ConstructorBuilder cb = builder as ConstructorBuilder;
 
-                       return p.ParameterType;
+                       for (int i = 0; i < FixedParameters.Length; i++) {
+                               FixedParameters [i].ApplyAttributes (mb, cb, i + 1);
+                       }
                }
 
-               public CallingConventions GetCallingConvention ()
+#if MS_COMPATIBLE
+               public ParameterData InflateTypes (Type[] genArguments, Type[] argTypes)
                {
-                       if (HasArglist)
-                               return CallingConventions.VarArgs;
-                       else
-                               return CallingConventions.Standard;
-               }
+                       Parameters p = Clone ();
+                       for (int i = 0; i < count; ++i) {
+                               if (types[i].IsGenericType) {
+                                       Type[] gen_arguments_open = new Type [types[i].GetGenericTypeDefinition ().GetGenericArguments ().Length];
+                                       Type[] gen_arguments = types[i].GetGenericArguments ();
+                                       for (int ii = 0; ii < gen_arguments_open.Length; ++ii) {
+                                               if (gen_arguments[ii].IsGenericParameter) {
+                                                       Type t = argTypes[gen_arguments[ii].GenericParameterPosition];
+                                                       gen_arguments_open[ii] = t;
+                                               } else
+                                                       gen_arguments_open[ii] = gen_arguments[ii];
+                                       }
 
-               //
-               // The method's attributes are passed in because we need to extract
-               // the "return:" attribute from there to apply on the return type
-               //
-               public void LabelParameters (EmitContext ec, MethodBase builder)
-               {
-                       //
-                       // Define each type attribute (in/out/ref) and
-                       // the argument names.
-                       //
-                       int i = 0;
-                       
-                       MethodBuilder mb = builder as MethodBuilder;
-                       ConstructorBuilder cb = builder as ConstructorBuilder;
+                                       p.FixedParameters [i].ParameterType = p.types[i] =
+                                               types[i].GetGenericTypeDefinition ().MakeGenericType (gen_arguments_open);
+                                       continue;
+                               }
 
-                       if (FixedParameters != null) {
-                               for (i = 0; i < FixedParameters.Length; i++) {
-                                       FixedParameters [i].DefineParameter (ec, mb, cb, i + 1);
+                               if (types[i].IsGenericParameter) {
+                                       Type gen_argument = argTypes[types[i].GenericParameterPosition];
+                                       p.FixedParameters[i].ParameterType = p.types[i] = gen_argument;
+                                       continue;
                                }
                        }
 
-                       if (ArrayParameter != null){
-                               ParameterBuilder pb;
-                               Parameter array_param = ArrayParameter;
+                       return p;
+               }
+#endif
 
-                               if (mb == null)
-                                       pb = cb.DefineParameter (
-                                               i + 1, array_param.Attributes,
-                                               array_param.Name);
-                               else
-                                       pb = mb.DefineParameter (
-                                               i + 1, array_param.Attributes,
-                                               array_param.Name);
-                                       
-                               CustomAttributeBuilder a = new CustomAttributeBuilder (
-                                       TypeManager.cons_param_array_attribute, new object [0]);
-                               
-                               pb.SetCustomAttribute (a);
-                       }
+               public void VerifyClsCompliance ()
+               {
+                       foreach (Parameter p in FixedParameters)
+                               p.IsClsCompliant ();
                }
 
                public string GetSignatureForError ()
                {
                        StringBuilder sb = new StringBuilder ("(");
-                       if (FixedParameters != null) {
+                       if (count > 0) {
                                for (int i = 0; i < FixedParameters.Length; ++i) {
                                        sb.Append (FixedParameters[i].GetSignatureForError ());
                                        if (i < FixedParameters.Length - 1)
                                                sb.Append (", ");
                                }
                        }
+
+                       if (HasArglist) {
+                               if (sb.Length > 1)
+                                       sb.Append (", ");
+                               sb.Append ("__arglist");
+                       }
+
                        sb.Append (')');
                        return sb.ToString ();
+               }
+
+               public Type[] Types {
+                       get {
+                               return types;
+                       }
+                       //
+                       // Dangerous, used by implicit lambda parameters
+                       // only to workaround bad design
+                       //
+                       set {
+                               types = value;
+                       }
+               }
+
+               public Parameter this [int pos]
+               {
+                       get {
+                               if (pos >= count && (HasArglist || HasParams)) {
+                                       if (HasArglist && (pos == 0 || pos >= count))
+                                               return ArgList;
+                                       pos = count - 1;
+                               }
+
+                               return FixedParameters [pos];
+                       }
+               }
+
+               #region ParameterData Members
+
+               public Type ParameterType (int pos)
+               {
+                       return this [pos].ExternalType ();
+               }
 
+               public bool HasParams {
+                       get {
+                               if (count == 0)
+                                       return false;
+
+                               for (int i = count; i != 0; --i) {
+                                       if ((FixedParameters [i - 1].ModFlags & Parameter.Modifier.PARAMS) != 0)
+                                               return true;
+                               }
+                               return false;
+                       }
                }
+
+               public string ParameterName (int pos)
+               {
+                       return this [pos].Name;
+               }
+
+               public string ParameterDesc (int pos)
+               {
+                       return this [pos].GetSignatureForError ();
+               }
+
+               public Parameter.Modifier ParameterModifier (int pos)
+               {
+                       return this [pos].ModFlags;
+               }
+
+               public Parameters Clone ()
+               {
+                       Parameter [] parameters_copy = new Parameter [FixedParameters.Length];
+                       int i = 0;
+                       foreach (Parameter p in FixedParameters)
+                               parameters_copy [i++] = p.Clone ();
+                       Parameters ps = new Parameters (parameters_copy, HasArglist);
+                       if (types != null)
+                               ps.types = (Type[])types.Clone ();
+                       return ps;
+               }
+               
+               #endregion
        }
 }