date
[mono.git] / mcs / mcs / parameter.cs
index eff976d93414f3e61d60f54f935aa31588a9f606..25a7bba803c54eabc7e5864f8f9107423d5f2ed4 100755 (executable)
@@ -23,19 +23,21 @@ namespace Mono.CSharp {
        public class Parameter {
                [Flags]
                public enum Modifier : byte {
-                       NONE   = 0,
-                       REF    = 1,
-                       OUT    = 2,
-                       PARAMS = 4,
+                       NONE    = 0,
+                       REF     = 1,
+                       OUT     = 2,
+                       PARAMS  = 4,
+                       // This is a flag which says that it's either REF or OUT.
+                       ISBYREF = 8
                }
 
-               public readonly string   TypeName;
-               public readonly string   Name;
+               public readonly Expression TypeName;
                public readonly Modifier ModFlags;
                public Attributes OptAttributes;
-               public Type ParameterType;
+               public readonly string Name;
+               public Type parameter_type;
                
-               public Parameter (string type, string name, Modifier mod, Attributes attrs)
+               public Parameter (Expression type, string name, Modifier mod, Attributes attrs)
                {
                        Name = name;
                        ModFlags = mod;
@@ -43,38 +45,39 @@ namespace Mono.CSharp {
                        OptAttributes = attrs;
                }
 
-               public bool Resolve (DeclSpace ds)
+               // <summary>
+               //   Resolve is used in method definitions
+               // </summary>
+               public bool Resolve (DeclSpace ds, Location l)
                {
-                       ParameterType = ds.LookupType (TypeName, false);
-                       return ParameterType != null;
+                       parameter_type = ds.ResolveType (TypeName, false, l);
+
+                       if (parameter_type == TypeManager.void_type){
+                               Report.Error (1536, l, "`void' parameter is not permitted");
+                               return false;
+                       }
+                       
+                       return parameter_type != null;
                }
 
-               public Type ExternalType ()
+               public Type ExternalType (DeclSpace ds, Location l)
                {
-                       if ((ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0){
-                               string n = ParameterType.FullName + "&";
-                               Type t;
-                               
-                               t = Type.GetType (n);
-
-                               //
-                               // It is a type defined by the source code we are compiling
-                               //
-                               if (t == null){
-                                       ModuleBuilder mb = RootContext.ModuleBuilder;
-
-                                       t = mb.GetType (n);
-                               }
+                       if ((ModFlags & Parameter.Modifier.ISBYREF) != 0)
+                               return TypeManager.GetReferenceType (parameter_type);
+                       
+                       return parameter_type;
+               }
 
-                               return t;
+               public Type ParameterType {
+                       get {
+                               return parameter_type;
                        }
-
-                       return ParameterType;
                }
                
                public ParameterAttributes Attributes {
                        get {
-                               switch (ModFlags){
+                               int flags = ((int) ModFlags) & ~((int) Parameter.Modifier.ISBYREF);
+                               switch ((Modifier) flags) {
                                case Modifier.NONE:
                                        return ParameterAttributes.None;
                                case Modifier.REF:
@@ -93,14 +96,14 @@ namespace Mono.CSharp {
                ///   Returns the signature for this parameter evaluating it on the
                ///   @tc context
                /// </summary>
-               public string GetSignature (DeclSpace ds)
+               public string GetSignature (DeclSpace ds, Location loc)
                {
-                       if (ParameterType == null){
-                               if (!Resolve (ds))
+                       if (parameter_type == null){
+                               if (!Resolve (ds, loc))
                                        return null;
                        }
 
-                       return ExternalType ().FullName;
+                       return ExternalType (ds, loc).FullName;
                }
        }
 
@@ -112,25 +115,28 @@ namespace Mono.CSharp {
                public readonly Parameter ArrayParameter;
                string signature;
                Type [] types;
+               Location loc;
                
                static Parameters empty_parameters;
                
-               public Parameters (Parameter [] fixed_parameters, Parameter array_parameter)
+               public Parameters (Parameter [] fixed_parameters, Parameter array_parameter, Location l)
                {
                        FixedParameters = fixed_parameters;
                        ArrayParameter  = array_parameter;
+                       loc = l;
                }
 
                /// <summary>
                ///   This is used to reuse a set of empty parameters, because they
                ///   are common
                /// </summary>
-               public static Parameters GetEmptyReadOnlyParameters ()
-               {
-                       if (empty_parameters == null)
-                               empty_parameters = new Parameters (null, null);
+               public static Parameters EmptyReadOnlyParameters {
+                       get {
+                               if (empty_parameters == null)
+                                       empty_parameters = new Parameters (null, null, Location.Null);
                        
-                       return empty_parameters;
+                               return empty_parameters;
+                       }
                }
                
                public bool Empty {
@@ -139,14 +145,14 @@ namespace Mono.CSharp {
                        }
                }
                
-               public void ComputeSignature (TypeContainer tc)
+               public void ComputeSignature (DeclSpace ds)
                {
                        signature = "";
                        if (FixedParameters != null){
                                for (int i = 0; i < FixedParameters.Length; i++){
                                        Parameter par = FixedParameters [i];
                                        
-                                       signature += par.GetSignature (tc);
+                                       signature += par.GetSignature (ds, loc);
                                }
                        }
                        //
@@ -155,7 +161,13 @@ namespace Mono.CSharp {
                        //
                }
 
-               public bool VerifyArgs (TypeContainer tc)
+               static void Error_DuplicateParameterName (string name)
+               {
+                       Report.Error (
+                               100, "The parameter name `" + name + "' is a duplicate");
+               }
+               
+               public bool VerifyArgs ()
                {
                        int count;
                        int i, j;
@@ -164,13 +176,19 @@ namespace Mono.CSharp {
                                return true;
                        
                        count = FixedParameters.Length;
+                       string array_par_name = ArrayParameter != null ? ArrayParameter.Name : null;
                        for (i = 0; i < count; i++){
+                               string base_name = FixedParameters [i].Name;
+                               
                                for (j = i + 1; j < count; j++){
-                                       if (FixedParameters [i].Name != FixedParameters [j].Name)
+                                       if (base_name != FixedParameters [j].Name)
                                                continue;
-                                       Report.Error (
-                                               100, "The parameter name `" + FixedParameters [i].Name +
-                                               "' is a duplicate");
+                                       Error_DuplicateParameterName (base_name);
+                                       return false;
+                               }
+
+                               if (base_name == array_par_name){
+                                       Error_DuplicateParameterName (base_name);
                                        return false;
                                }
                        }
@@ -181,11 +199,11 @@ namespace Mono.CSharp {
                ///    Returns the signature of the Parameters evaluated in
                ///    the @tc environment
                /// </summary>
-               public string GetSignature (TypeContainer tc)
+               public string GetSignature (DeclSpace ds)
                {
                        if (signature == null){
-                               VerifyArgs (tc);
-                               ComputeSignature (tc);
+                               VerifyArgs ();
+                               ComputeSignature (ds);
                        }
                        
                        return signature;
@@ -197,57 +215,129 @@ namespace Mono.CSharp {
                public Parameter GetParameterByName (string name, out int idx)
                {
                        idx = 0;
-
-                       if (FixedParameters == null)
-                               return null;
-
                        int i = 0;
-                       foreach (Parameter par in FixedParameters){
-                               if (par.Name == name){
-                                       idx = i;
-                                       return par;
+
+                       if (FixedParameters != null){
+                               foreach (Parameter par in FixedParameters){
+                                       if (par.Name == name){
+                                               idx = i;
+                                               return par;
+                                       }
+                                       i++;
                                }
-                               i++;
                        }
 
-                       if (ArrayParameter != null)
+                       if (ArrayParameter != null){
                                if (name == ArrayParameter.Name){
                                        idx = i;
                                        return ArrayParameter;
                                }
+                       }
                        
                        return null;
                }
 
-               bool ComputeParameterTypes (TypeContainer tc)
+               bool ComputeParameterTypes (DeclSpace ds)
                {
                        int extra = (ArrayParameter != null) ? 1 : 0;
                        int i = 0;
-                       int pc = FixedParameters.Length + extra;
-                       
+                       int pc;
+
+                       if (FixedParameters == null)
+                               pc = extra;
+                       else
+                               pc = extra + FixedParameters.Length;
+
                        types = new Type [pc];
                        
-                       if (!VerifyArgs (tc)){
+                       if (!VerifyArgs ()){
                                FixedParameters = null;
                                return false;
                        }
+
+                       bool failed = false;
+                       if (FixedParameters != null){
+                               foreach (Parameter p in FixedParameters){
+                                       Type t = null;
+                                       
+                                       if (p.Resolve (ds, loc))
+                                               t = p.ExternalType (ds, loc);
+                                       else
+                                               failed = true;
+                                       
+                                       types [i] = t;
+                                       i++;
+                               }
+                       }
+                       
+                       if (extra > 0){
+                               if (ArrayParameter.Resolve (ds, loc))
+                                       types [i] = ArrayParameter.ExternalType (ds, loc);
+                               else 
+                                       failed = true;
+                       }
+
+                       if (failed){
+                               types = null;
+                               return false;
+                       }
+
+                       return true;
+               }
+
+               //
+               // This variant is used by Delegates, because they need to
+               // resolve/define names, instead of the plain LookupType
+               //
+               public bool ComputeAndDefineParameterTypes (DeclSpace ds)
+               {
+                       int extra = (ArrayParameter != null) ? 1 : 0;
+                       int i = 0;
+                       int pc;
+
+                       if (FixedParameters == null)
+                               pc = extra;
+                       else
+                               pc = extra + FixedParameters.Length;
                        
-                       foreach (Parameter p in FixedParameters){
-                               Type t = null;
-                               
-                               if (p.Resolve (tc))
-                                       t = p.ExternalType ();
-                               
-                               types [i] = t;
-                               i++;
+                       types = new Type [pc];
+                       
+                       if (!VerifyArgs ()){
+                               FixedParameters = null;
+                               return false;
                        }
 
+                       bool ok_flag = true;
+                       
+                       if (FixedParameters != null){
+                               foreach (Parameter p in FixedParameters){
+                                       Type t = null;
+                                       
+                                       if (p.Resolve (ds, loc))
+                                               t = p.ExternalType (ds, loc);
+                                       else
+                                               ok_flag = false;
+                                       
+                                       types [i] = t;
+                                       i++;
+                               }
+                       }
+                       
                        if (extra > 0){
-                               if (ArrayParameter.Resolve (tc))
-                                       types [i] = ArrayParameter.ExternalType ();
+                               if (ArrayParameter.Resolve (ds, loc))
+                                       types [i] = ArrayParameter.ExternalType (ds, loc);
+                               else
+                                       ok_flag = false;
                        }
 
-                       return true;
+                       //
+                       // invalidate the cached types
+                       //
+                       if (!ok_flag){
+                               types = null;
+                       }
+                       
+                       return ok_flag;
                }
                
                /// <summary>
@@ -255,17 +345,19 @@ namespace Mono.CSharp {
                /// </summary>
                static Type [] no_types = new Type [0];
                
-               public Type [] GetParameterInfo (TypeContainer tc)
+               public Type [] GetParameterInfo (DeclSpace ds)
                {
                        if (types != null)
                                return types;
                        
-                       if (FixedParameters == null)
+                       if (FixedParameters == null && ArrayParameter == null)
                                return no_types;
 
-                       if (ComputeParameterTypes (tc) == false)
+                       if (ComputeParameterTypes (ds) == false){
+                               types = null;
                                return null;
-                       
+                       }
+
                        return types;
                }
 
@@ -276,37 +368,37 @@ namespace Mono.CSharp {
                ///   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 (TypeContainer tc, int idx, out bool is_out)
+               public Type GetParameterInfo (DeclSpace ds, int idx, out Parameter.Modifier mod)
                {
-                       is_out = false;
+                       mod = Parameter.Modifier.NONE;
                        
-                       if (!VerifyArgs (tc)){
+                       if (!VerifyArgs ()){
                                FixedParameters = null;
                                return null;
                        }
 
-                       if (FixedParameters == null)
+                       if (FixedParameters == null && ArrayParameter == null)
                                return null;
                        
                        if (types == null)
-                               if (ComputeParameterTypes (tc) == false){
-                                       is_out = false;
+                               if (ComputeParameterTypes (ds) == false)
                                        return null;
-                               }
 
                        //
                        // If this is a request for the variable lenght arg.
                        //
-                       if (idx == FixedParameters.Length){
-                               is_out = false;
+                       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];
-                       is_out = ((p.ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0);
+                       mod = p.ModFlags;
+
+                       if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0)
+                               mod |= Parameter.Modifier.ISBYREF;
 
                        return p.ParameterType;
                }