2002-02-25 Ravi Pratap <ravi@ximian.com>
[mono.git] / mcs / mcs / parameter.cs
1 //
2 // parameter.cs: Parameter definition.
3 //
4 // Author: Miguel de Icaza (miguel@gnu.org)
5 //
6 // Licensed under the terms of the GNU GPL
7 //
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
9 //
10 //
11 //
12 using System;
13 using System.Reflection;
14 using System.Reflection.Emit;
15 using System.Collections;
16
17 namespace Mono.CSharp {
18
19
20         /// <summary>
21         ///   Represents a single method parameter
22         /// </summary>
23         public class Parameter {
24                 [Flags]
25                 public enum Modifier : byte {
26                         NONE   = 0,
27                         REF    = 1,
28                         OUT    = 2,
29                         PARAMS = 4,
30                 }
31
32                 public readonly string   TypeName;
33                 public readonly string   Name;
34                 public readonly Modifier ModFlags;
35                 public Attributes OptAttributes;
36                 public Type ParameterType;
37                 
38                 public Parameter (string type, string name, Modifier mod, Attributes attrs)
39                 {
40                         Name = name;
41                         ModFlags = mod;
42                         TypeName = type;
43                         OptAttributes = attrs;
44                 }
45
46                 public bool Resolve (DeclSpace ds, Location l)
47                 {
48                         ParameterType = RootContext.LookupType (ds, TypeName, false, l);
49                         return ParameterType != null;
50                 }
51
52                 public Type ExternalType (DeclSpace ds, Location l)
53                 {
54                         if ((ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0){
55                                 string n = ParameterType.FullName + "&";
56
57                                 Type t = RootContext.LookupType (ds, n, false, l);
58
59                                 return t;
60                         }
61                         
62                         return ParameterType;
63                 }
64                 
65                 public ParameterAttributes Attributes {
66                         get {
67                                 switch (ModFlags){
68                                 case Modifier.NONE:
69                                         return ParameterAttributes.None;
70                                 case Modifier.REF:
71                                         return ParameterAttributes.None;
72                                 case Modifier.OUT:
73                                         return ParameterAttributes.Out;
74                                 case Modifier.PARAMS:
75                                         return 0;
76                                 }
77                                 
78                                 return ParameterAttributes.None;
79                         }
80                 }
81                 
82                 /// <summary>
83                 ///   Returns the signature for this parameter evaluating it on the
84                 ///   @tc context
85                 /// </summary>
86                 public string GetSignature (DeclSpace ds, Location loc)
87                 {
88                         if (ParameterType == null){
89                                 if (!Resolve (ds, loc))
90                                         return null;
91                         }
92
93                         return ExternalType (ds, loc).FullName;
94                 }
95         }
96
97         /// <summary>
98         ///   Represents the methods parameters
99         /// </summary>
100         public class Parameters {
101                 public Parameter [] FixedParameters;
102                 public readonly Parameter ArrayParameter;
103                 string signature;
104                 Type [] types;
105                 Location loc;
106                 
107                 static Parameters empty_parameters;
108                 
109                 public Parameters (Parameter [] fixed_parameters, Parameter array_parameter, Location l)
110                 {
111                         FixedParameters = fixed_parameters;
112                         ArrayParameter  = array_parameter;
113                         loc = l;
114                 }
115
116                 /// <summary>
117                 ///   This is used to reuse a set of empty parameters, because they
118                 ///   are common
119                 /// </summary>
120                 public static Parameters GetEmptyReadOnlyParameters ()
121                 {
122                         if (empty_parameters == null)
123                                 empty_parameters = new Parameters (null, null, Location.Null);
124                         
125                         return empty_parameters;
126                 }
127                 
128                 public bool Empty {
129                         get {
130                                 return (FixedParameters == null) && (ArrayParameter == null);
131                         }
132                 }
133                 
134                 public void ComputeSignature (DeclSpace ds)
135                 {
136                         signature = "";
137                         if (FixedParameters != null){
138                                 for (int i = 0; i < FixedParameters.Length; i++){
139                                         Parameter par = FixedParameters [i];
140                                         
141                                         signature += par.GetSignature (ds, loc);
142                                 }
143                         }
144                         //
145                         // Note: as per the spec, the `params' arguments (ArrayParameter)
146                         // are not used in the signature computation for a method
147                         //
148                 }
149
150                 static void error100 (string name)
151                 {
152                         Report.Error (
153                                 100, "The parameter name `" + name + "' is a duplicate");
154                 }
155                 
156                 public bool VerifyArgs ()
157                 {
158                         int count;
159                         int i, j;
160
161                         if (FixedParameters == null)
162                                 return true;
163                         
164                         count = FixedParameters.Length;
165                         string array_par_name = ArrayParameter != null ? ArrayParameter.Name : null;
166                         for (i = 0; i < count; i++){
167                                 string base_name = FixedParameters [i].Name;
168                                 
169                                 for (j = i + 1; j < count; j++){
170                                         if (base_name != FixedParameters [j].Name)
171                                                 continue;
172                                         error100 (base_name);
173                                         return false;
174                                 }
175
176                                 if (base_name == array_par_name){
177                                         error100 (base_name);
178                                         return false;
179                                 }
180                         }
181                         return true;
182                 }
183                 
184                 /// <summary>
185                 ///    Returns the signature of the Parameters evaluated in
186                 ///    the @tc environment
187                 /// </summary>
188                 public string GetSignature (DeclSpace ds)
189                 {
190                         if (signature == null){
191                                 VerifyArgs ();
192                                 ComputeSignature (ds);
193                         }
194                         
195                         return signature;
196                 }
197                 
198                 /// <summary>
199                 ///    Returns the paramenter information based on the name
200                 /// </summary>
201                 public Parameter GetParameterByName (string name, out int idx)
202                 {
203                         idx = 0;
204                         int i = 0;
205
206                         if (FixedParameters != null){
207                                 foreach (Parameter par in FixedParameters){
208                                         if (par.Name == name){
209                                                 idx = i;
210                                                 return par;
211                                         }
212                                         i++;
213                                 }
214                         }
215
216                         if (ArrayParameter != null){
217                                 if (name == ArrayParameter.Name){
218                                         idx = i;
219                                         return ArrayParameter;
220                                 }
221                         }
222                         
223                         return null;
224                 }
225
226                 bool ComputeParameterTypes (DeclSpace ds)
227                 {
228                         int extra = (ArrayParameter != null) ? 1 : 0;
229                         int i = 0;
230                         int pc;
231
232                         if (FixedParameters == null)
233                                 pc = extra;
234                         else
235                                 pc = extra + FixedParameters.Length;
236                         
237                         types = new Type [pc];
238                         
239                         if (!VerifyArgs ()){
240                                 FixedParameters = null;
241                                 return false;
242                         }
243
244                         if (FixedParameters != null){
245                                 foreach (Parameter p in FixedParameters){
246                                         Type t = null;
247                                         
248                                         if (p.Resolve (ds, loc))
249                                                 t = p.ExternalType (ds, loc);
250                                         
251                                         types [i] = t;
252                                         i++;
253                                 }
254                         }
255                         
256                         if (extra > 0){
257                                 if (ArrayParameter.Resolve (ds, loc))
258                                         types [i] = ArrayParameter.ExternalType (ds, loc);
259                         }
260
261                         return true;
262                 }
263                 
264                 /// <summary>
265                 ///   Returns the argument types as an array
266                 /// </summary>
267                 static Type [] no_types = new Type [0];
268                 
269                 public Type [] GetParameterInfo (DeclSpace ds)
270                 {
271                         if (types != null)
272                                 return types;
273                         
274                         if (FixedParameters == null && ArrayParameter == null)
275                                 return no_types;
276
277                         if (ComputeParameterTypes (ds) == false)
278                                 return null;
279                         
280                         return types;
281                 }
282
283                 /// <summary>
284                 ///   Returns the type of a given parameter, and stores in the `is_out'
285                 ///   boolean whether this is an out or ref parameter.
286                 ///
287                 ///   Note that the returned type will not contain any dereference in this
288                 ///   case (ie, you get "int" for a ref int instead of "int&"
289                 /// </summary>
290                 public Type GetParameterInfo (DeclSpace ds, int idx, out bool is_out)
291                 {
292                         is_out = false;
293                         
294                         if (!VerifyArgs ()){
295                                 FixedParameters = null;
296                                 return null;
297                         }
298
299                         if (FixedParameters == null && ArrayParameter == null)
300                                 return null;
301                         
302                         if (types == null)
303                                 if (ComputeParameterTypes (ds) == false){
304                                         is_out = false;
305                                         return null;
306                                 }
307
308                         //
309                         // If this is a request for the variable lenght arg.
310                         //
311                         int array_idx = (FixedParameters != null ? FixedParameters.Length : 0);
312                         if (idx == array_idx){
313                                 is_out = false;
314                                 return types [idx];
315                         } 
316
317                         //
318                         // Otherwise, it is a fixed parameter
319                         //
320                         Parameter p = FixedParameters [idx];
321                         is_out = ((p.ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0);
322
323                         return p.ParameterType;
324                 }
325
326                 public CallingConventions GetCallingConvention ()
327                 {
328                         // For now this is the only correc thing to do
329                         return CallingConventions.Standard;
330                 }
331         }
332 }
333                 
334         
335