e8558d8d574beee950f84ed9526fd1bf00b8a1a8
[mono.git] / mcs / mcs / support.cs
1 //
2 // support.cs: Support routines to work around the fact that System.Reflection.Emit
3 // can not introspect types that are being constructed
4 //
5 // Author:
6 //   Miguel de Icaza (miguel@ximian.com)
7 //
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
9 //
10
11 using System;
12 using System.Text;
13 using System.Reflection;
14 using System.Collections;
15 using System.Reflection.Emit;
16 using System.Globalization;
17
18 namespace Mono.CSharp {
19
20         public interface ParameterData {
21                 Type ParameterType (int pos);
22                 int  Count { get; }
23                 string ParameterName (int pos);
24                 string ParameterDesc (int pos);
25                 Parameter.Modifier ParameterModifier (int pos);
26         }
27
28         public class ReflectionParameters : ParameterData {
29                 ParameterInfo [] pi;
30                 bool last_arg_is_params = false;
31                 
32                 public ReflectionParameters (ParameterInfo [] pi)
33                 {
34                         object [] attrs;
35                         
36                         this.pi = pi;
37                         int count = pi.Length-1;
38
39                         if (count >= 0) {
40                                 attrs = pi [count].GetCustomAttributes (TypeManager.param_array_type, true);
41
42                                 if (attrs == null)
43                                         return;
44                                 
45                                 if (attrs.Length == 0)
46                                         return;
47
48                                 last_arg_is_params = true;
49                         }
50                 }
51                        
52                 public Type ParameterType (int pos)
53                 {
54                         if (last_arg_is_params && pos >= pi.Length - 1)
55                                 return pi [pi.Length - 1].ParameterType;
56                         else 
57                                 return pi [pos].ParameterType;
58                 }
59
60                 public string ParameterName (int pos)
61                 {
62                         if (last_arg_is_params && pos >= pi.Length - 1)
63                                 return pi [pi.Length - 1].Name;
64                         else 
65                                 return pi [pos].Name;
66                 }
67
68                 public string ParameterDesc (int pos)
69                 {
70                         StringBuilder sb = new StringBuilder ();
71
72                         if (pi [pos].IsOut)
73                                 sb.Append ("out ");
74
75                         if (pi [pos].IsIn)
76                                 sb.Append ("in ");
77
78                         if (pos >= pi.Length - 1 && last_arg_is_params)
79                                 sb.Append ("params ");
80                         
81                         sb.Append (TypeManager.CSharpName (ParameterType (pos)));
82
83                         return sb.ToString ();
84                         
85                 }
86
87                 public Parameter.Modifier ParameterModifier (int pos)
88                 {
89                         int len = pi.Length;
90                         
91                         if (pos >= len - 1)
92                                 if (last_arg_is_params)
93                                         return Parameter.Modifier.PARAMS;
94                         
95                         Type t = pi [pos].ParameterType;
96                         if (t.IsByRef){
97                                 if ((pi [pos].Attributes & ParameterAttributes.Out) != 0)
98                                         return Parameter.Modifier.ISBYREF | Parameter.Modifier.OUT;
99                                 else
100                                         return Parameter.Modifier.ISBYREF | Parameter.Modifier.REF;
101                         }
102                         
103                         return Parameter.Modifier.NONE;
104                 }
105
106                 public int Count {
107                         get {
108                                 return pi.Length;
109                         }
110                 }
111                 
112         }
113
114         public class InternalParameters : ParameterData {
115                 Type [] param_types;
116
117                 public readonly Parameters Parameters;
118                 
119                 public InternalParameters (Type [] param_types, Parameters parameters)
120                 {
121                         this.param_types = param_types;
122                         this.Parameters = parameters;
123                 }
124
125                 public InternalParameters (DeclSpace ds, Parameters parameters)
126                         : this (parameters.GetParameterInfo (ds), parameters)
127                 {
128                 }
129
130                 public int Count {
131                         get {
132                                 if (param_types == null)
133                                         return 0;
134
135                                 return param_types.Length;
136                         }
137                 }
138
139                 public Type ParameterType (int pos)
140                 {
141                         if (param_types == null)
142                                 return null;
143
144                         Parameter [] fixed_pars = Parameters.FixedParameters;
145                         if (fixed_pars != null){
146                                 int len = fixed_pars.Length;
147                                 if (pos < len)
148                                         return Parameters.FixedParameters [pos].ParameterType;
149                                 else 
150                                         return Parameters.ArrayParameter.ParameterType;
151                         } else
152                                 return Parameters.ArrayParameter.ParameterType;
153                 }
154
155                 public string ParameterName (int pos)
156                 {
157                         Parameter p;
158
159                         if (pos >= Parameters.FixedParameters.Length)
160                                 p = Parameters.ArrayParameter;
161                         else
162                                 p = Parameters.FixedParameters [pos];
163
164                         return p.Name;
165                 }
166
167                 public string ParameterDesc (int pos)
168                 {
169                         string tmp = String.Empty;
170                         Parameter p;
171
172                         if (pos >= Parameters.FixedParameters.Length)
173                                 p = Parameters.ArrayParameter;
174                         else
175                                 p = Parameters.FixedParameters [pos];
176
177                         //
178                         // We need to and for REF/OUT, because if either is set the
179                         // extra flag ISBYREF will be set as well
180                         //
181                         if ((p.ModFlags & Parameter.Modifier.REF) != 0)
182                                 tmp = "ref ";
183                         else if ((p.ModFlags & Parameter.Modifier.OUT) != 0)
184                                 tmp = "out ";
185                         else if (p.ModFlags == Parameter.Modifier.PARAMS)
186                                 tmp = "params ";
187
188                         Type t = ParameterType (pos);
189
190                         return tmp + TypeManager.CSharpName (t);
191                 }
192
193                 public Parameter.Modifier ParameterModifier (int pos)
194                 {
195                         Parameter.Modifier mod;
196
197                         if (Parameters.FixedParameters == null) {
198                                 if (Parameters.ArrayParameter != null) 
199                                         mod = Parameters.ArrayParameter.ModFlags;
200                                 else
201                                         mod = Parameter.Modifier.NONE;
202                         } else if (pos >= Parameters.FixedParameters.Length)
203                                 mod = Parameters.ArrayParameter.ModFlags;
204                         else
205                                 mod = Parameters.FixedParameters [pos].ModFlags;
206
207                         if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0)
208                                 mod |= Parameter.Modifier.ISBYREF;
209
210                         return mod;
211                 }
212                 
213         }
214
215         class PtrHashtable : Hashtable {
216                 class PtrComparer : IComparer {
217                         public int Compare (object x, object y)
218                         {
219                                 if (x == y)
220                                         return 0;
221                                 else
222                                         return 1;
223                         }
224                 }
225                 
226                 public PtrHashtable ()
227                 {
228                         comparer = new PtrComparer ();
229                 }
230         }
231
232         //
233         // Compares member infos based on their name and
234         // also allows one argument to be a string
235         //
236         class MemberInfoCompare : IComparer {
237
238                 public int Compare (object a, object b)
239                 {
240                         if (a == null || b == null){
241                                 Console.WriteLine ("Invalid information passed");
242                                 throw new Exception ();
243                         }
244                         
245                         if (a is string)
246                                 return String.Compare ((string) a, ((MemberInfo)b).Name);
247
248                         if (b is string)
249                                 return String.Compare (((MemberInfo)a).Name, (string) b);
250
251                         return String.Compare (((MemberInfo)a).Name, ((MemberInfo)b).Name);
252                 }
253         }
254
255         struct Pair {
256                 public object First;
257                 public object Second;
258                 
259                 public Pair (object f, object s)
260                 {
261                         First = f;
262                         Second = s;
263                 }
264         }
265 }