fix for different results message
[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                         if (pi [pos].DefaultValue == null)
72                                 return NullLiteral.Null;
73                         Type type = pi [pos].DefaultValue.GetType();
74
75                         //
76                         // TODO : Enum is not handled here since ParameterInfo
77                         // is not returning correct Data type for Enum
78                         //
79                         switch (Type.GetTypeCode(type)){
80                                 case TypeCode.Byte:
81                                         return new ByteConstant ((byte) pi [pos].DefaultValue);
82                                 case TypeCode.Char:
83                                         return new CharConstant ((char) pi [pos].DefaultValue);
84                                 case TypeCode.String:
85                                         return new StringConstant ((string) pi [pos].DefaultValue);
86                                 case TypeCode.Int16:
87                                         return new ShortConstant ((short) pi [pos].DefaultValue);
88                                 case TypeCode.UInt16:
89                                         return new UShortConstant ((ushort) pi [pos].DefaultValue);
90                                 case TypeCode.Int32:
91                                         return new IntConstant ((int) pi [pos].DefaultValue);
92                                 case TypeCode.UInt32:
93                                         return new UIntConstant ((uint) pi [pos].DefaultValue);
94                                 case TypeCode.Int64:
95                                         return new LongConstant ((long) pi [pos].DefaultValue);
96                                 case TypeCode.UInt64:
97                                         return new ULongConstant ((ulong) pi [pos].DefaultValue);
98                                 case TypeCode.Boolean:
99                                         return new BoolConstant ((bool) pi [pos].DefaultValue);
100                                 case TypeCode.DateTime:
101                                         return new DateConstant ((DateTime) pi [pos].DefaultValue);
102                                 case TypeCode.Decimal:
103                                         return new DecimalConstant ((decimal) pi [pos].DefaultValue);
104                                 case TypeCode.Double:
105                                         return new DoubleConstant ((double) pi [pos].DefaultValue);
106                                 case TypeCode.SByte:
107                                         return new SByteConstant ((sbyte) pi [pos].DefaultValue);
108                                 default:
109                                         Report.Error(-1, 
110                                         "Internal Error : cannot handle the data type" +
111                                         "received from ParameterInfo class");
112                                         return null;
113                         }
114 #if false
115                         if (last_arg_is_params && pos >= pi.Length - 1)
116                                 return pi [pi.Length - 1].ParameterType;
117                         else
118                                 if (pos >= pi.Length)
119                                         return null;
120                                 else {
121                                         Type pt = pi [pos].ParameterType;
122                                         if (pt.IsByRef)
123                                                 pt = pt.GetElementType();
124                                         return pt;
125                                 }
126 #endif
127                 }
128
129                 public string ParameterName (int pos)
130                 {
131                         if (last_arg_is_params && pos >= pi.Length - 1)
132                                 return pi [pi.Length - 1].Name;
133                         else 
134                                 return pi [pos].Name;
135                 }
136
137                 public string ParameterDesc (int pos)
138                 {
139                         StringBuilder sb = new StringBuilder ();
140
141                         if (pi [pos].IsOut)
142                                 sb.Append ("out ");
143
144                         if (pi [pos].IsIn)
145                                 sb.Append ("in ");
146
147                         if (pos >= pi.Length - 1 && last_arg_is_params)
148                                 sb.Append ("params ");
149                         
150                         sb.Append (TypeManager.MonoBASIC_Name (ParameterType (pos)));
151
152                         return sb.ToString ();
153                         
154                 }
155
156                 public Parameter.Modifier ParameterModifier (int pos)
157                 {
158                         int len = pi.Length;
159                         Parameter.Modifier pm = Parameter.Modifier.NONE;
160
161                         if (pos >= len - 1)
162                                 if (last_arg_is_params) {
163                                         pm |= Parameter.Modifier.PARAMS;
164                                         pos = len - 1;
165                                 }
166                         
167                         Type t = pi [pos].ParameterType;
168                         if (t.IsByRef)
169                                 pm |= Parameter.Modifier.ISBYREF | Parameter.Modifier.REF;
170
171                         if (pi [pos].IsOptional)
172                                 pm |= Parameter.Modifier.OPTIONAL;
173                         
174                         return pm;
175                 }
176
177                 public int Count {
178                         get {
179                                 return pi.Length;
180                         }
181                 }
182                 
183         }
184
185         public class InternalParameters : ParameterData {
186                 Type [] param_types;
187
188                 public readonly Parameters Parameters;
189                 
190                 public InternalParameters (Type [] param_types, Parameters parameters)
191                 {
192                         this.param_types = param_types;
193                         this.Parameters = parameters;
194                 }
195
196                 public InternalParameters (DeclSpace ds, Parameters parameters)
197                         : this (parameters.GetParameterInfo (ds), parameters)
198                 {
199                 }
200
201                 public int Count {
202                         get {
203                                 if (param_types == null)
204                                         return 0;
205
206                                 return param_types.Length;
207                         }
208                 }
209
210                 public Type ParameterType (int pos)
211                 {
212                         if (param_types == null)
213                                 return null;
214
215                         Parameter [] fixed_pars = Parameters.FixedParameters;
216                         if (fixed_pars != null && pos < fixed_pars.Length)
217                                 return Parameters.FixedParameters [pos].ParameterType;
218                         else 
219                                 return Parameters.ArrayParameter.ParameterType;
220                 }
221
222                 public Expression DefaultValue (int pos)
223                 {
224                         Parameter [] fixed_pars = Parameters.FixedParameters;
225                         if (fixed_pars != null && pos < fixed_pars.Length)
226                                 return Parameters.FixedParameters [pos].ParameterInitializer;
227                         return null;
228                 }
229
230                 public string ParameterName (int pos)
231                 {
232                         Parameter p;
233
234                         if (pos >= Parameters.FixedParameters.Length)
235                                 p = Parameters.ArrayParameter;
236                         else
237                                 p = Parameters.FixedParameters [pos];
238
239                         return p.Name;
240                 }
241
242                 public string ParameterDesc (int pos)
243                 {
244                         string tmp = String.Empty;
245                         Parameter p;
246
247                         if (Parameters.FixedParameters == null || pos >= Parameters.FixedParameters.Length)
248                                 p = Parameters.ArrayParameter;
249                         else
250                                 p = Parameters.FixedParameters [pos];
251                         
252                         if (p.ModFlags == Parameter.Modifier.REF)
253                                 tmp = "ref ";
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 )) != 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 }