Fix for build breakage on cygwin-head-mono
[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                         Type type = pi [pos].DefaultValue.GetType();
72
73                         //
74                         // TODO : Enum is not handled here since ParameterInfo
75                         // is not returning correct Data type for Enum
76                         //
77                         switch (Type.GetTypeCode(type)){
78                                 case TypeCode.Byte:
79                                         return new ByteConstant ((byte) pi [pos].DefaultValue);
80                                 case TypeCode.Char:
81                                         return new CharConstant ((char) pi [pos].DefaultValue);
82                                 case TypeCode.String:
83                                         return new StringConstant ((string) pi [pos].DefaultValue);
84                                 case TypeCode.Int16:
85                                         return new ShortConstant ((short) pi [pos].DefaultValue);
86                                 case TypeCode.UInt16:
87                                         return new UShortConstant ((ushort) pi [pos].DefaultValue);
88                                 case TypeCode.Int32:
89                                         return new IntConstant ((int) pi [pos].DefaultValue);
90                                 case TypeCode.UInt32:
91                                         return new UIntConstant ((uint) pi [pos].DefaultValue);
92                                 case TypeCode.Int64:
93                                         return new LongConstant ((long) pi [pos].DefaultValue);
94                                 case TypeCode.UInt64:
95                                         return new ULongConstant ((ulong) pi [pos].DefaultValue);
96                                 case TypeCode.Boolean:
97                                         return new BoolConstant ((bool) pi [pos].DefaultValue);
98                                 case TypeCode.DateTime:
99                                         return new DateConstant ((DateTime) pi [pos].DefaultValue);
100                                 case TypeCode.Decimal:
101                                         return new DecimalConstant ((decimal) pi [pos].DefaultValue);
102                                 case TypeCode.Double:
103                                         return new DoubleConstant ((double) pi [pos].DefaultValue);
104                                 case TypeCode.SByte:
105                                         return new SByteConstant ((sbyte) pi [pos].DefaultValue);
106                                 default:
107                                         Report.Error(-1, 
108                                         "Internal Error : cannot handle the data type" +
109                                         "received from ParameterInfo class");
110                                         return null;
111                         }
112 #if false
113                         if (last_arg_is_params && pos >= pi.Length - 1)
114                                 return pi [pi.Length - 1].ParameterType;
115                         else
116                                 if (pos >= pi.Length)
117                                         return null;
118                                 else {
119                                         Type pt = pi [pos].ParameterType;
120                                         if (pt.IsByRef)
121                                                 pt = pt.GetElementType();
122                                         return pt;
123                                 }
124 #endif
125                 }
126
127                 public string ParameterName (int pos)
128                 {
129                         if (last_arg_is_params && pos >= pi.Length - 1)
130                                 return pi [pi.Length - 1].Name;
131                         else 
132                                 return pi [pos].Name;
133                 }
134
135                 public string ParameterDesc (int pos)
136                 {
137                         StringBuilder sb = new StringBuilder ();
138
139                         if (pi [pos].IsOut)
140                                 sb.Append ("out ");
141
142                         if (pi [pos].IsIn)
143                                 sb.Append ("in ");
144
145                         if (pos >= pi.Length - 1 && last_arg_is_params)
146                                 sb.Append ("params ");
147                         
148                         sb.Append (TypeManager.MonoBASIC_Name (ParameterType (pos)));
149
150                         return sb.ToString ();
151                         
152                 }
153
154                 public Parameter.Modifier ParameterModifier (int pos)
155                 {
156                         int len = pi.Length;
157                         Parameter.Modifier pm = Parameter.Modifier.NONE;
158
159                         if (pos >= len - 1)
160                                 if (last_arg_is_params) {
161                                         pm |= Parameter.Modifier.PARAMS;
162                                         pos = len - 1;
163                                 }
164                         
165                         Type t = pi [pos].ParameterType;
166                         if (t.IsByRef)
167                                 pm |= Parameter.Modifier.ISBYREF | Parameter.Modifier.REF;
168
169                         if (pi [pos].IsOptional)
170                                 pm |= Parameter.Modifier.OPTIONAL;
171                         
172                         return pm;
173                 }
174
175                 public int Count {
176                         get {
177                                 return pi.Length;
178                         }
179                 }
180                 
181         }
182
183         public class InternalParameters : ParameterData {
184                 Type [] param_types;
185
186                 public readonly Parameters Parameters;
187                 
188                 public InternalParameters (Type [] param_types, Parameters parameters)
189                 {
190                         this.param_types = param_types;
191                         this.Parameters = parameters;
192                 }
193
194                 public InternalParameters (DeclSpace ds, Parameters parameters)
195                         : this (parameters.GetParameterInfo (ds), parameters)
196                 {
197                 }
198
199                 public int Count {
200                         get {
201                                 if (param_types == null)
202                                         return 0;
203
204                                 return param_types.Length;
205                         }
206                 }
207
208                 public Type ParameterType (int pos)
209                 {
210                         if (param_types == null)
211                                 return null;
212
213                         Parameter [] fixed_pars = Parameters.FixedParameters;
214                         if (fixed_pars != null && pos < fixed_pars.Length)
215                                 return Parameters.FixedParameters [pos].ParameterType;
216                         else 
217                                 return Parameters.ArrayParameter.ParameterType;
218                 }
219
220                 public Expression DefaultValue (int pos)
221                 {
222                         Parameter [] fixed_pars = Parameters.FixedParameters;
223                         if (fixed_pars != null && pos < fixed_pars.Length)
224                                 return Parameters.FixedParameters [pos].ParameterInitializer;
225                         return null;
226                 }
227
228                 public string ParameterName (int pos)
229                 {
230                         Parameter p;
231
232                         if (pos >= Parameters.FixedParameters.Length)
233                                 p = Parameters.ArrayParameter;
234                         else
235                                 p = Parameters.FixedParameters [pos];
236
237                         return p.Name;
238                 }
239
240                 public string ParameterDesc (int pos)
241                 {
242                         string tmp = String.Empty;
243                         Parameter p;
244
245                         if (Parameters.FixedParameters == null || pos >= Parameters.FixedParameters.Length)
246                                 p = Parameters.ArrayParameter;
247                         else
248                                 p = Parameters.FixedParameters [pos];
249                         
250                         if (p.ModFlags == Parameter.Modifier.REF)
251                                 tmp = "ref ";
252                         else if (p.ModFlags == Parameter.Modifier.OUT)
253                                 tmp = "out ";
254                         else if (p.ModFlags == Parameter.Modifier.PARAMS)
255                                 tmp = "params ";
256
257                         Type t = ParameterType (pos);
258
259                         return tmp + TypeManager.MonoBASIC_Name (t);
260                 }
261
262                 public Parameter.Modifier ParameterModifier (int pos)
263                 {
264                         Parameter.Modifier mod;
265
266                         if (Parameters.FixedParameters == null) {
267                                 if (Parameters.ArrayParameter != null) 
268                                         mod = Parameters.ArrayParameter.ModFlags;
269                                 else
270                                         mod = Parameter.Modifier.NONE;
271                         } else if (pos >= Parameters.FixedParameters.Length)
272                                 mod = Parameters.ArrayParameter.ModFlags;
273                         else
274                                 mod = Parameters.FixedParameters [pos].ModFlags;
275
276                         if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0)
277                                 mod |= Parameter.Modifier.ISBYREF;
278
279                         return mod;
280                 }
281                 
282         }
283
284         class PtrHashtable : Hashtable {
285                 class PtrComparer : IComparer {
286                         public int Compare (object x, object y)
287                         {
288                                 if (x == y)
289                                         return 0;
290                                 else
291                                         return 1;
292                         }
293                 }
294                 
295                 public PtrHashtable ()
296                 {
297                         comparer = new PtrComparer ();
298                         hcp = new CaseInsensitiveHashCodeProvider();
299                 }
300         }
301         
302
303         public class CaseInsensitiveHashtable : Hashtable {
304                 public CaseInsensitiveHashtable() : base()
305                 {
306                         comparer = new CaseInsensitiveComparer();
307                         hcp = new CaseInsensitiveHashCodeProvider();
308                 }
309         }
310
311         //
312         // Compares member infos based on their name and
313         // also allows one argument to be a string
314         //
315         class MemberInfoCompare : IComparer {
316
317                 public int Compare (object a, object b)
318                 {
319                         if (a == null || b == null){
320                                 Console.WriteLine ("Invalid information passed");
321                                 throw new Exception ();
322                         }
323                         
324                         if (a is string)
325                                 return String.Compare ((string) a, ((MemberInfo)b).Name);
326
327                         if (b is string)
328                                 return String.Compare (((MemberInfo)a).Name, (string) b);
329
330                         return String.Compare (((MemberInfo)a).Name, ((MemberInfo)b).Name);
331                 }
332         }
333
334         struct Pair {
335                 public object First;
336                 public object Second;
337                 
338                 public Pair (object f, object s)
339                 {
340                         First = f;
341                         Second = s;
342                 }
343         }
344 }