2007-01-03 Chris Toshok <toshok@ximian.com>
[mono.git] / mcs / mcs / parameter.cs
index 288e1af8a07b5ed7245fe73703d67429cd2d1d66..80fc9753ca47e6b8da596f07efaf3539a5122d69 100644 (file)
@@ -24,12 +24,10 @@ namespace Mono.CSharp {
        public abstract class ParameterBase : Attributable {
 
                protected ParameterBuilder builder;
-               public readonly Location Location;
 
-               protected ParameterBase (Attributes attrs, Location loc)
+               protected ParameterBase (Attributes attrs)
                        : base (attrs)
                {
-                       Location = loc;
                }
 
                public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
@@ -50,7 +48,7 @@ namespace Mono.CSharp {
                        builder.SetCustomAttribute (cb);
                }
 
-               public override bool IsClsComplianceRequired(DeclSpace ds)
+               public override bool IsClsComplianceRequired()
                {
                        return false;
                }
@@ -61,13 +59,13 @@ namespace Mono.CSharp {
        /// </summary>
        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.RuntimeMissingSupport (Location, "custom attributes on the return type");
+                               Report.RuntimeMissingSupport (location, "custom attributes on the return type");
                        }
                }
 
@@ -90,6 +88,12 @@ namespace Mono.CSharp {
                        }
                }
 
+               public override IResolveContext ResolveContext {
+                       get {
+                               throw new NotSupportedException ();
+                       }
+               }
+
                /// <summary>
                /// Is never called
                /// </summary>
@@ -107,8 +111,8 @@ namespace Mono.CSharp {
        /// 
        // TODO: should use more code from Parameter.ApplyAttributeBuilder
        public class ImplicitParameter : ParameterBase {
-               public ImplicitParameter (MethodBuilder mb, Location loc):
-                       base (null, loc)
+               public ImplicitParameter (MethodBuilder mb):
+                       base (null)
                {
                        builder = mb.DefineParameter (1, ParameterAttributes.None, "");                 
                }
@@ -119,6 +123,12 @@ namespace Mono.CSharp {
                        }
                }
 
+               public override IResolveContext ResolveContext {
+                       get {
+                               throw new NotSupportedException ();
+                       }
+               }
+
                /// <summary>
                /// Is never called
                /// </summary>
@@ -135,7 +145,7 @@ namespace Mono.CSharp {
                {
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (IResolveContext ec)
                {
                        if (!base.Resolve (ec))
                                return false;
@@ -147,12 +157,12 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public override void ApplyAttributes (EmitContext ec, MethodBuilder mb, ConstructorBuilder cb, int index)
+               public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index)
                {
-                       base.ApplyAttributes (ec, mb, cb, index);
+                       base.ApplyAttributes (mb, cb, index);
 
                        CustomAttributeBuilder a = new CustomAttributeBuilder (
-                               TypeManager.cons_param_array_attribute, new object [0]);
+                               TypeManager.ConsParamArrayAttribute, new object [0]);
                                
                        builder.SetCustomAttribute (a);
                }
@@ -165,7 +175,7 @@ namespace Mono.CSharp {
                {
                }
 
-               public override bool Resolve (EmitContext ec)
+               public override bool Resolve (IResolveContext ec)
                {
                        return true;
                }
@@ -197,25 +207,38 @@ namespace Mono.CSharp {
 
                public Expression TypeName;
                public readonly Modifier ModFlags;
-               public readonly string Name;
+               public string Name;
+               public bool IsCaptured;
                protected Type parameter_type;
+               public readonly Location Location;
+
+               IResolveContext resolve_context;
 
-               EmitContext ec;  // because ApplyAtrribute doesn't have ec
+               Variable var;
+               public Variable Variable {
+                       get { return var; }
+               }
+
+#if GMCS_SOURCE
+               GenericConstraints constraints;
+#endif
                
                public Parameter (Expression type, string name, Modifier mod, Attributes attrs, Location loc)
-                       : base (attrs, loc)
+                       : base (attrs)
                {
                        Name = name;
                        ModFlags = mod;
                        TypeName = type;
+                       Location = loc;
                }
 
                public Parameter (Type type, string name, Modifier mod, Attributes attrs, Location loc)
-                       : base (attrs, loc)
+                       : base (attrs)
                {
                        Name = name;
                        ModFlags = mod;
                        parameter_type = type;
+                       Location = loc;
                }
 
                public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
@@ -231,7 +254,7 @@ namespace Mono.CSharp {
                        }
 
                        if (a.Type == TypeManager.out_attribute_type && (ModFlags & Modifier.REF) == Modifier.REF &&
-                           !OptAttributes.Contains (TypeManager.in_attribute_type, ec)) {
+                           !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;
@@ -241,24 +264,65 @@ 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
+                       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 override IResolveContext ResolveContext {
+                       get {
+                               return resolve_context;
+                       }
+               }
+
                // <summary>
                //   Resolve is used in method definitions
                // </summary>
-               public virtual bool Resolve (EmitContext ec)
+               public virtual bool Resolve (IResolveContext ec)
                {
                        if (parameter_type != null)
                                return true;
 
-                       this.ec = ec;
+                       this.resolve_context = ec;
 
                        TypeExpr texpr = TypeName.ResolveAsTypeTerminal (ec, false);
                        if (texpr == null)
                                return false;
 
-                       parameter_type = texpr.ResolveType (ec);
+#if GMCS_SOURCE
+                       TypeParameterExpr tparam = texpr as TypeParameterExpr;
+                       if (tparam != null)
+                               constraints = tparam.TypeParameter.Constraints;
+#endif
+
+                       parameter_type = texpr.Type;
                        
                        if (parameter_type.IsAbstract && parameter_type.IsSealed) {
                                Report.Error (721, Location, "`{0}': static types cannot be used as parameters", GetSignatureForError ());
@@ -282,6 +346,14 @@ namespace Mono.CSharp {
                        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)
@@ -295,7 +367,15 @@ namespace Mono.CSharp {
                                return parameter_type;
                        }
                }
-               
+
+#if GMCS_SOURCE
+               public GenericConstraints GenericConstraints {
+                       get {
+                               return constraints;
+                       }
+               }
+#endif
+
                public ParameterAttributes Attributes {
                        get {
                                switch (ModFlags) {
@@ -312,6 +392,23 @@ namespace Mono.CSharp {
                                return ParameterAttributes.None;
                        }
                }
+
+               public static ParameterAttributes GetParameterAttributes (Modifier mod)
+               {
+                       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 {
@@ -358,15 +455,18 @@ namespace Mono.CSharp {
                        Report.Error (3001, Location, "Argument type `{0}' is not CLS-compliant", GetSignatureForError ());
                }
 
-               public virtual void ApplyAttributes (EmitContext ec, MethodBuilder mb, ConstructorBuilder cb, int index)
+               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, Attributes, Name);
                        else 
                                builder = mb.DefineParameter (index, Attributes, Name);
-               
+#endif
+
                        if (OptAttributes != null)
-                               OptAttributes.Emit (ec, this);
+                               OptAttributes.Emit ();
                }
 
                public override string[] ValidAttributeTargets {
@@ -374,6 +474,78 @@ 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);
+                               }
+                       }
+               }
+
        }
 
        /// <summary>
@@ -389,13 +561,24 @@ namespace Mono.CSharp {
                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];
                }
+
+               public Parameters (Parameter[] parameters, Type[] types)
+               {
+                       FixedParameters = parameters;
+                       this.types = types;
+                       count = types.Length;
+               }
                
-               public Parameters (Parameter [] parameters)
+               public Parameters (Parameter[] parameters)
                {
                        if (parameters == null)
                                throw new ArgumentException ("Use EmptyReadOnlyPatameters");
@@ -410,6 +593,31 @@ namespace Mono.CSharp {
                        HasArglist = has_arglist;
                }
 
+               /// <summary>
+               /// Use this method when you merge compiler generated argument with user arguments
+               /// </summary>
+               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 count == 0;
@@ -471,16 +679,15 @@ namespace Mono.CSharp {
                        return GetParameterByName (name, out idx);
                }
                
-               public bool Resolve (EmitContext ec)
+               public bool Resolve (IResolveContext ec)
                {
                        if (types != null)
                                return true;
 
                        types = new Type [count];
                        
-                       if (ec != null && !VerifyArgs ()){
+                       if (!VerifyArgs ())
                                return false;
-                       }
 
                        bool ok = true;
                        Parameter p;
@@ -496,6 +703,14 @@ namespace Mono.CSharp {
                        return ok;
                }
 
+               public void ResolveVariable (ToplevelBlock toplevel)
+               {
+                       for (int i = 0; i < FixedParameters.Length; ++i) {
+                               Parameter p = FixedParameters [i];
+                               p.ResolveVariable (toplevel, i);
+                       }
+               }
+
                public CallingConventions CallingConvention
                {
                        get {
@@ -508,7 +723,7 @@ namespace Mono.CSharp {
 
                // Define each type attribute (in/out/ref) and
                // the argument names.
-               public void ApplyAttributes (EmitContext ec, MethodBase builder)
+               public void ApplyAttributes (MethodBase builder)
                {
                        if (count == 0)
                                return;
@@ -517,7 +732,7 @@ namespace Mono.CSharp {
                        ConstructorBuilder cb = builder as ConstructorBuilder;
 
                        for (int i = 0; i < FixedParameters.Length; i++) {
-                               FixedParameters [i].ApplyAttributes (ec, mb, cb, i + 1);
+                               FixedParameters [i].ApplyAttributes (mb, cb, i + 1);
                        }
                }
 
@@ -539,11 +754,9 @@ namespace Mono.CSharp {
                        }
 
                        if (HasArglist) {
-                               if (HasArglist) {
-                                       if (sb.Length > 1)
-                                               sb.Append (", ");
-                                       sb.Append ("__arglist");
-                               }
+                               if (sb.Length > 1)
+                                       sb.Append (", ");
+                               sb.Append ("__arglist");
                        }
 
                        sb.Append (')');
@@ -556,7 +769,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               Parameter this [int pos]
+               public Parameter this [int pos]
                {
                        get {
                                if (pos >= count && (HasArglist || HasParams)) {
@@ -581,7 +794,11 @@ namespace Mono.CSharp {
                                if (count == 0)
                                        return false;
 
-                               return FixedParameters [count - 1] is ParamsParameter;
+                               for (int i = count; i != 0; --i) {
+                                       if ((FixedParameters [i - 1].ModFlags & Parameter.Modifier.PARAMS) != 0)
+                                               return true;
+                               }
+                               return false;
                        }
                }