Use TypeManager.GetInterfaces().
[mono.git] / mcs / gmcs / 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                         // This is a flag which says that it's either REF or OUT.
31                         ISBYREF = 8
32                 }
33
34                 public readonly Expression TypeName;
35                 public readonly Modifier ModFlags;
36                 public Attributes OptAttributes;
37                 public readonly string Name;
38                 GenericConstraints constraints;
39                 Type parameter_type;
40                 
41                 public Parameter (Expression type, string name, Modifier mod, Attributes attrs)
42                 {
43                         Name = name;
44                         ModFlags = mod;
45                         TypeName = type;
46                         OptAttributes = attrs;
47                 }
48
49                 // <summary>
50                 //   Resolve is used in method definitions
51                 // </summary>
52                 public bool Resolve (DeclSpace ds, Location l)
53                 {
54                         TypeExpr texpr = ds.ResolveTypeExpr (TypeName, false, l);
55                         if (texpr == null)
56                                 return false;
57
58                         TypeParameterExpr tparam = texpr as TypeParameterExpr;
59                         if (tparam != null)
60                                 constraints = tparam.TypeParameter.Constraints;
61
62                         parameter_type = ds.ResolveType (texpr, l);
63
64                         if (parameter_type == TypeManager.void_type){
65                                 Report.Error (1536, l, "`void' parameter is not permitted");
66                                 return false;
67                         }
68
69                         return parameter_type != null;
70                 }
71
72                 public Type ExternalType ()
73                 {
74                         if ((ModFlags & Parameter.Modifier.ISBYREF) != 0)
75                                 return TypeManager.GetReferenceType (parameter_type);
76                         
77                         return parameter_type;
78                 }
79
80                 public Type ParameterType {
81                         get {
82                                 return parameter_type;
83                         }
84                 }
85
86                 public GenericConstraints GenericConstraints {
87                         get {
88                                 return constraints;
89                         }
90                 }
91                 
92                 public ParameterAttributes Attributes {
93                         get {
94                                 int flags = ((int) ModFlags) & ~((int) Parameter.Modifier.ISBYREF);
95                                 switch ((Modifier) flags) {
96                                 case Modifier.NONE:
97                                         return ParameterAttributes.None;
98                                 case Modifier.REF:
99                                         return ParameterAttributes.None;
100                                 case Modifier.OUT:
101                                         return ParameterAttributes.Out;
102                                 case Modifier.PARAMS:
103                                         return 0;
104                                 }
105                                 
106                                 return ParameterAttributes.None;
107                         }
108                 }
109                 
110                 /// <summary>
111                 ///   Returns the signature for this parameter evaluating it on the
112                 ///   @tc context
113                 /// </summary>
114                 public string GetSignature (DeclSpace ds, Location loc)
115                 {
116                         if (parameter_type == null){
117                                 if (!Resolve (ds, loc))
118                                         return null;
119                         }
120
121                         return ExternalType ().FullName;
122                 }
123         }
124
125         /// <summary>
126         ///   Represents the methods parameters
127         /// </summary>
128         public class Parameters {
129                 public Parameter [] FixedParameters;
130                 public readonly Parameter ArrayParameter;
131                 string signature;
132                 Type [] types;
133                 Location loc;
134                 
135                 static Parameters empty_parameters;
136                 
137                 public Parameters (Parameter [] fixed_parameters, Parameter array_parameter, Location l)
138                 {
139                         FixedParameters = fixed_parameters;
140                         ArrayParameter  = array_parameter;
141                         loc = l;
142                 }
143
144                 /// <summary>
145                 ///   This is used to reuse a set of empty parameters, because they
146                 ///   are common
147                 /// </summary>
148                 public static Parameters EmptyReadOnlyParameters {
149                         get {
150                                 if (empty_parameters == null)
151                                         empty_parameters = new Parameters (null, null, Location.Null);
152                         
153                                 return empty_parameters;
154                         }
155                 }
156                 
157                 public bool Empty {
158                         get {
159                                 return (FixedParameters == null) && (ArrayParameter == null);
160                         }
161                 }
162                 
163                 public void ComputeSignature (DeclSpace ds)
164                 {
165                         signature = "";
166                         if (FixedParameters != null){
167                                 for (int i = 0; i < FixedParameters.Length; i++){
168                                         Parameter par = FixedParameters [i];
169                                         
170                                         signature += par.GetSignature (ds, loc);
171                                 }
172                         }
173                         //
174                         // Note: as per the spec, the `params' arguments (ArrayParameter)
175                         // are not used in the signature computation for a method
176                         //
177                 }
178
179                 void Error_DuplicateParameterName (string name)
180                 {
181                         Report.Error (
182                                 100, loc, "The parameter name `" + name + "' is a duplicate");
183                 }
184                 
185                 public bool VerifyArgs ()
186                 {
187                         int count;
188                         int i, j;
189
190                         if (FixedParameters == null)
191                                 return true;
192                         
193                         count = FixedParameters.Length;
194                         string array_par_name = ArrayParameter != null ? ArrayParameter.Name : null;
195                         for (i = 0; i < count; i++){
196                                 string base_name = FixedParameters [i].Name;
197                                 
198                                 for (j = i + 1; j < count; j++){
199                                         if (base_name != FixedParameters [j].Name)
200                                                 continue;
201                                         Error_DuplicateParameterName (base_name);
202                                         return false;
203                                 }
204
205                                 if (base_name == array_par_name){
206                                         Error_DuplicateParameterName (base_name);
207                                         return false;
208                                 }
209                         }
210                         return true;
211                 }
212                 
213                 /// <summary>
214                 ///    Returns the signature of the Parameters evaluated in
215                 ///    the @tc environment
216                 /// </summary>
217                 public string GetSignature (DeclSpace ds)
218                 {
219                         if (signature == null){
220                                 VerifyArgs ();
221                                 ComputeSignature (ds);
222                         }
223                         
224                         return signature;
225                 }
226                 
227                 /// <summary>
228                 ///    Returns the paramenter information based on the name
229                 /// </summary>
230                 public Parameter GetParameterByName (string name, out int idx)
231                 {
232                         idx = 0;
233                         int i = 0;
234
235                         if (FixedParameters != null){
236                                 foreach (Parameter par in FixedParameters){
237                                         if (par.Name == name){
238                                                 idx = i;
239                                                 return par;
240                                         }
241                                         i++;
242                                 }
243                         }
244
245                         if (ArrayParameter != null){
246                                 if (name == ArrayParameter.Name){
247                                         idx = i;
248                                         return ArrayParameter;
249                                 }
250                         }
251                         
252                         return null;
253                 }
254
255                 bool ComputeParameterTypes (DeclSpace ds)
256                 {
257                         int extra = (ArrayParameter != null) ? 1 : 0;
258                         int i = 0;
259                         int pc;
260
261                         if (FixedParameters == null)
262                                 pc = extra;
263                         else
264                                 pc = extra + FixedParameters.Length;
265
266                         types = new Type [pc];
267                         
268                         if (!VerifyArgs ()){
269                                 FixedParameters = null;
270                                 return false;
271                         }
272
273                         bool failed = false;
274                         if (FixedParameters != null){
275                                 foreach (Parameter p in FixedParameters){
276                                         Type t = null;
277                                         
278                                         if (p.Resolve (ds, loc))
279                                                 t = p.ExternalType ();
280                                         else
281                                                 failed = true;
282
283                                         types [i] = t;
284                                         i++;
285                                 }
286                         }
287                         
288                         if (extra > 0){
289                                 if (ArrayParameter.Resolve (ds, loc))
290                                         types [i] = ArrayParameter.ExternalType ();
291                                 else 
292                                         failed = true;
293                         }
294
295                         if (failed){
296                                 types = null;
297                                 return false;
298                         }
299
300                         return true;
301                 }
302
303                 //
304                 // This variant is used by Delegates, because they need to
305                 // resolve/define names, instead of the plain LookupType
306                 //
307                 public bool ComputeAndDefineParameterTypes (DeclSpace ds)
308                 {
309                         int extra = (ArrayParameter != null) ? 1 : 0;
310                         int i = 0;
311                         int pc;
312
313                         if (FixedParameters == null)
314                                 pc = extra;
315                         else
316                                 pc = extra + FixedParameters.Length;
317                         
318                         types = new Type [pc];
319                         
320                         if (!VerifyArgs ()){
321                                 FixedParameters = null;
322                                 return false;
323                         }
324
325                         bool ok_flag = true;
326                         
327                         if (FixedParameters != null){
328                                 foreach (Parameter p in FixedParameters){
329                                         Type t = null;
330                                         
331                                         if (p.Resolve (ds, loc))
332                                                 t = p.ExternalType ();
333                                         else
334                                                 ok_flag = false;
335                                         
336                                         types [i] = t;
337                                         i++;
338                                 }
339                         }
340                         
341                         if (extra > 0){
342                                 if (ArrayParameter.Resolve (ds, loc))
343                                         types [i] = ArrayParameter.ExternalType ();
344                                 else
345                                         ok_flag = false;
346                         }
347
348                         //
349                         // invalidate the cached types
350                         //
351                         if (!ok_flag){
352                                 types = null;
353                         }
354                         
355                         return ok_flag;
356                 }
357                 
358                 /// <summary>
359                 ///   Returns the argument types as an array
360                 /// </summary>
361                 static Type [] no_types = new Type [0];
362                 
363                 public Type [] GetParameterInfo (DeclSpace ds)
364                 {
365                         if (types != null)
366                                 return types;
367                         
368                         if (FixedParameters == null && ArrayParameter == null)
369                                 return no_types;
370
371                         if (ComputeParameterTypes (ds) == false){
372                                 types = null;
373                                 return null;
374                         }
375
376                         return types;
377                 }
378
379                 /// <summary>
380                 ///   Returns the type of a given parameter, and stores in the `is_out'
381                 ///   boolean whether this is an out or ref parameter.
382                 ///
383                 ///   Note that the returned type will not contain any dereference in this
384                 ///   case (ie, you get "int" for a ref int instead of "int&"
385                 /// </summary>
386                 public Type GetParameterInfo (DeclSpace ds, int idx, out Parameter.Modifier mod)
387                 {
388                         mod = Parameter.Modifier.NONE;
389                         
390                         if (!VerifyArgs ()){
391                                 FixedParameters = null;
392                                 return null;
393                         }
394
395                         if (FixedParameters == null && ArrayParameter == null)
396                                 return null;
397                         
398                         if (types == null)
399                                 if (ComputeParameterTypes (ds) == false)
400                                         return null;
401
402                         //
403                         // If this is a request for the variable lenght arg.
404                         //
405                         int array_idx = (FixedParameters != null ? FixedParameters.Length : 0);
406                         if (idx == array_idx)
407                                 return types [idx];
408
409                         //
410                         // Otherwise, it is a fixed parameter
411                         //
412                         Parameter p = FixedParameters [idx];
413                         mod = p.ModFlags;
414
415                         if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0)
416                                 mod |= Parameter.Modifier.ISBYREF;
417
418                         return p.ParameterType;
419                 }
420
421                 public CallingConventions GetCallingConvention ()
422                 {
423                         // For now this is the only correc thing to do
424                         return CallingConventions.Standard;
425                 }
426         }
427 }
428                 
429         
430