2007-01-03 Chris Toshok <toshok@ximian.com>
[mono.git] / mcs / mcs / parameter.cs
index ff1a60a077b1d7283f97d734f70047e7575a9e58..80fc9753ca47e6b8da596f07efaf3539a5122d69 100644 (file)
@@ -208,10 +208,20 @@ namespace Mono.CSharp {
                public Expression TypeName;
                public readonly Modifier ModFlags;
                public string Name;
+               public bool IsCaptured;
                protected Type parameter_type;
                public readonly Location Location;
 
                IResolveContext resolve_context;
+
+               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)
@@ -257,6 +267,23 @@ namespace Mono.CSharp {
                        // 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))
@@ -289,6 +316,12 @@ namespace Mono.CSharp {
                        if (texpr == null)
                                return false;
 
+#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) {
@@ -313,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)
@@ -326,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) {
@@ -343,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 {
@@ -391,11 +457,14 @@ namespace Mono.CSharp {
 
                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 ();
                }
@@ -405,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>
@@ -420,6 +561,10 @@ 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];
@@ -558,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 {
@@ -616,7 +769,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               Parameter this [int pos]
+               public Parameter this [int pos]
                {
                        get {
                                if (pos >= count && (HasArglist || HasParams)) {
@@ -641,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;
                        }
                }