**** Merged from MCS ****
[mono.git] / mcs / mbas / 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.MonoBASIC {
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                 Expression DefaultValue (int pos);
26                 Parameter.Modifier ParameterModifier (int pos);
27         }
28
29         public class ReflectionParameters : ParameterData {
30                 ParameterInfo [] pi;
31                 bool last_arg_is_params = false;
32                 
33                 public ReflectionParameters (ParameterInfo [] pi)
34                 {
35                         object [] attrs;
36                         
37                         this.pi = pi;
38
39                         int count = pi.Length-1;
40
41                         if (count >= 0) {
42                                 attrs = pi [count].GetCustomAttributes (TypeManager.param_array_type, true);
43
44                                 if (attrs == null)
45                                         return;
46                                 
47                                 if (attrs.Length == 0)
48                                         return;
49
50                                 last_arg_is_params = true;
51                         }
52                 }
53                        
54                 public Type ParameterType (int pos)
55                 {
56                         if (last_arg_is_params && pos >= pi.Length - 1)
57                                 return pi [pi.Length - 1].ParameterType;
58                         else
59                                 if (pos >= pi.Length)
60                                         return null;
61                                 else {
62                                         Type pt = pi [pos].ParameterType;
63                                         if (pt.IsByRef)
64                                                 pt = pt.GetElementType();
65                                         return pt;
66                                 }
67                 }
68
69                 public Expression DefaultValue (int pos)
70                 {
71                         return null;
72 #if false
73                         if (last_arg_is_params && pos >= pi.Length - 1)
74                                 return pi [pi.Length - 1].ParameterType;
75                         else
76                                 if (pos >= pi.Length)
77                                         return null;
78                                 else {
79                                         Type pt = pi [pos].ParameterType;
80                                         if (pt.IsByRef)
81                                                 pt = pt.GetElementType();
82                                         return pt;
83                                 }
84 #endif
85                 }
86
87                 public string ParameterName (int pos)
88                 {
89                         if (last_arg_is_params && pos >= pi.Length - 1)
90                                 return pi [pi.Length - 1].Name;
91                         else 
92                                 return pi [pos].Name;
93                 }
94
95                 public string ParameterDesc (int pos)
96                 {
97                         StringBuilder sb = new StringBuilder ();
98
99                         if (pi [pos].IsOut)
100                                 sb.Append ("out ");
101
102                         if (pi [pos].IsIn)
103                                 sb.Append ("in ");
104
105                         if (pos >= pi.Length - 1 && last_arg_is_params)
106                                 sb.Append ("params ");
107                         
108                         sb.Append (TypeManager.MonoBASIC_Name (ParameterType (pos)));
109
110                         return sb.ToString ();
111                         
112                 }
113
114                 public Parameter.Modifier ParameterModifier (int pos)
115                 {
116                         int len = pi.Length;
117                         Parameter.Modifier pm = Parameter.Modifier.NONE;
118
119                         if (pos >= len - 1)
120                                 if (last_arg_is_params) {
121                                         pm |= Parameter.Modifier.PARAMS;
122                                         pos = len - 1;
123                                 }
124                         
125                         Type t = pi [pos].ParameterType;
126                         if (t.IsByRef)
127                                 pm |= Parameter.Modifier.ISBYREF | Parameter.Modifier.REF;
128
129                         if (pi [pos].IsOptional)
130                                 pm |= Parameter.Modifier.OPTIONAL;
131                         
132                         return pm;
133                 }
134
135                 public int Count {
136                         get {
137                                 return pi.Length;
138                         }
139                 }
140                 
141         }
142
143         public class InternalParameters : ParameterData {
144                 Type [] param_types;
145
146                 public readonly Parameters Parameters;
147                 
148                 public InternalParameters (Type [] param_types, Parameters parameters)
149                 {
150                         this.param_types = param_types;
151                         this.Parameters = parameters;
152                 }
153
154                 public InternalParameters (DeclSpace ds, Parameters parameters)
155                         : this (parameters.GetParameterInfo (ds), parameters)
156                 {
157                 }
158
159                 public int Count {
160                         get {
161                                 if (param_types == null)
162                                         return 0;
163
164                                 return param_types.Length;
165                         }
166                 }
167
168                 public Type ParameterType (int pos)
169                 {
170                         if (param_types == null)
171                                 return null;
172
173                         Parameter [] fixed_pars = Parameters.FixedParameters;
174                         if (fixed_pars != null && pos < fixed_pars.Length)
175                                 return Parameters.FixedParameters [pos].ParameterType;
176                         else 
177                                 return Parameters.ArrayParameter.ParameterType;
178                 }
179
180                 public Expression DefaultValue (int pos)
181                 {
182                         Parameter [] fixed_pars = Parameters.FixedParameters;
183                         if (fixed_pars != null && pos < fixed_pars.Length)
184                                 return Parameters.FixedParameters [pos].ParameterInitializer;
185                         return null;
186                 }
187
188                 public string ParameterName (int pos)
189                 {
190                         Parameter p;
191
192                         if (pos >= Parameters.FixedParameters.Length)
193                                 p = Parameters.ArrayParameter;
194                         else
195                                 p = Parameters.FixedParameters [pos];
196
197                         return p.Name;
198                 }
199
200                 public string ParameterDesc (int pos)
201                 {
202                         string tmp = String.Empty;
203                         Parameter p;
204
205                         if (Parameters.FixedParameters == null || pos >= Parameters.FixedParameters.Length)
206                                 p = Parameters.ArrayParameter;
207                         else
208                                 p = Parameters.FixedParameters [pos];
209                         
210                         if (p.ModFlags == Parameter.Modifier.REF)
211                                 tmp = "ref ";
212                         else if (p.ModFlags == Parameter.Modifier.OUT)
213                                 tmp = "out ";
214                         else if (p.ModFlags == Parameter.Modifier.PARAMS)
215                                 tmp = "params ";
216
217                         Type t = ParameterType (pos);
218
219                         return tmp + TypeManager.MonoBASIC_Name (t);
220                 }
221
222                 public Parameter.Modifier ParameterModifier (int pos)
223                 {
224                         Parameter.Modifier mod;
225
226                         if (Parameters.FixedParameters == null) {
227                                 if (Parameters.ArrayParameter != null) 
228                                         mod = Parameters.ArrayParameter.ModFlags;
229                                 else
230                                         mod = Parameter.Modifier.NONE;
231                         } else if (pos >= Parameters.FixedParameters.Length)
232                                 mod = Parameters.ArrayParameter.ModFlags;
233                         else
234                                 mod = Parameters.FixedParameters [pos].ModFlags;
235
236                         if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0)
237                                 mod |= Parameter.Modifier.ISBYREF;
238
239                         return mod;
240                 }
241                 
242         }
243
244         class PtrHashtable : Hashtable {
245                 class PtrComparer : IComparer {
246                         public int Compare (object x, object y)
247                         {
248                                 if (x == y)
249                                         return 0;
250                                 else
251                                         return 1;
252                         }
253                 }
254                 
255                 public PtrHashtable ()
256                 {
257                         comparer = new PtrComparer ();
258                         hcp = new CaseInsensitiveHashCodeProvider();
259                 }
260         }
261         
262
263         public class CaseInsensitiveHashtable : Hashtable {
264                 public CaseInsensitiveHashtable() : base()
265                 {
266                         comparer = new CaseInsensitiveComparer();
267                         hcp = new CaseInsensitiveHashCodeProvider();
268                 }
269         }
270
271         //
272         // Compares member infos based on their name and
273         // also allows one argument to be a string
274         //
275         class MemberInfoCompare : IComparer {
276
277                 public int Compare (object a, object b)
278                 {
279                         if (a == null || b == null){
280                                 Console.WriteLine ("Invalid information passed");
281                                 throw new Exception ();
282                         }
283                         
284                         if (a is string)
285                                 return String.Compare ((string) a, ((MemberInfo)b).Name);
286
287                         if (b is string)
288                                 return String.Compare (((MemberInfo)a).Name, (string) b);
289
290                         return String.Compare (((MemberInfo)a).Name, ((MemberInfo)b).Name);
291                 }
292         }
293
294         struct Pair {
295                 public object First;
296                 public object Second;
297                 
298                 public Pair (object f, object s)
299                 {
300                         First = f;
301                         Second = s;
302                 }
303         }
304 }