**** Merged from MCS ****
[mono-project.git] / mcs / mbas / support.cs
blob1a3e4cc7017b044e4049c60b44a143a2f7e79ef4
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 //
11 using System;
12 using System.Text;
13 using System.Reflection;
14 using System.Collections;
15 using System.Reflection.Emit;
16 using System.Globalization;
18 namespace Mono.MonoBASIC {
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);
29 public class ReflectionParameters : ParameterData {
30 ParameterInfo [] pi;
31 bool last_arg_is_params = false;
33 public ReflectionParameters (ParameterInfo [] pi)
35 object [] attrs;
37 this.pi = pi;
39 int count = pi.Length-1;
41 if (count >= 0) {
42 attrs = pi [count].GetCustomAttributes (TypeManager.param_array_type, true);
44 if (attrs == null)
45 return;
47 if (attrs.Length == 0)
48 return;
50 last_arg_is_params = true;
54 public Type ParameterType (int pos)
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;
69 public Expression DefaultValue (int pos)
71 Type type = pi [pos].DefaultValue.GetType();
74 // TODO : Enum is not handled here since ParameterInfo
75 // is not returning correct Data type for Enum
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;
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;
124 #endif
127 public string ParameterName (int pos)
129 if (last_arg_is_params && pos >= pi.Length - 1)
130 return pi [pi.Length - 1].Name;
131 else
132 return pi [pos].Name;
135 public string ParameterDesc (int pos)
137 StringBuilder sb = new StringBuilder ();
139 if (pi [pos].IsOut)
140 sb.Append ("out ");
142 if (pi [pos].IsIn)
143 sb.Append ("in ");
145 if (pos >= pi.Length - 1 && last_arg_is_params)
146 sb.Append ("params ");
148 sb.Append (TypeManager.MonoBASIC_Name (ParameterType (pos)));
150 return sb.ToString ();
154 public Parameter.Modifier ParameterModifier (int pos)
156 int len = pi.Length;
157 Parameter.Modifier pm = Parameter.Modifier.NONE;
159 if (pos >= len - 1)
160 if (last_arg_is_params) {
161 pm |= Parameter.Modifier.PARAMS;
162 pos = len - 1;
165 Type t = pi [pos].ParameterType;
166 if (t.IsByRef)
167 pm |= Parameter.Modifier.ISBYREF | Parameter.Modifier.REF;
169 if (pi [pos].IsOptional)
170 pm |= Parameter.Modifier.OPTIONAL;
172 return pm;
175 public int Count {
176 get {
177 return pi.Length;
183 public class InternalParameters : ParameterData {
184 Type [] param_types;
186 public readonly Parameters Parameters;
188 public InternalParameters (Type [] param_types, Parameters parameters)
190 this.param_types = param_types;
191 this.Parameters = parameters;
194 public InternalParameters (DeclSpace ds, Parameters parameters)
195 : this (parameters.GetParameterInfo (ds), parameters)
199 public int Count {
200 get {
201 if (param_types == null)
202 return 0;
204 return param_types.Length;
208 public Type ParameterType (int pos)
210 if (param_types == null)
211 return null;
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;
220 public Expression DefaultValue (int pos)
222 Parameter [] fixed_pars = Parameters.FixedParameters;
223 if (fixed_pars != null && pos < fixed_pars.Length)
224 return Parameters.FixedParameters [pos].ParameterInitializer;
225 return null;
228 public string ParameterName (int pos)
230 Parameter p;
232 if (pos >= Parameters.FixedParameters.Length)
233 p = Parameters.ArrayParameter;
234 else
235 p = Parameters.FixedParameters [pos];
237 return p.Name;
240 public string ParameterDesc (int pos)
242 string tmp = String.Empty;
243 Parameter p;
245 if (Parameters.FixedParameters == null || pos >= Parameters.FixedParameters.Length)
246 p = Parameters.ArrayParameter;
247 else
248 p = Parameters.FixedParameters [pos];
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 ";
257 Type t = ParameterType (pos);
259 return tmp + TypeManager.MonoBASIC_Name (t);
262 public Parameter.Modifier ParameterModifier (int pos)
264 Parameter.Modifier mod;
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;
276 if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0)
277 mod |= Parameter.Modifier.ISBYREF;
279 return mod;
284 class PtrHashtable : Hashtable {
285 class PtrComparer : IComparer {
286 public int Compare (object x, object y)
288 if (x == y)
289 return 0;
290 else
291 return 1;
295 public PtrHashtable ()
297 comparer = new PtrComparer ();
298 hcp = new CaseInsensitiveHashCodeProvider();
303 public class CaseInsensitiveHashtable : Hashtable {
304 public CaseInsensitiveHashtable() : base()
306 comparer = new CaseInsensitiveComparer();
307 hcp = new CaseInsensitiveHashCodeProvider();
312 // Compares member infos based on their name and
313 // also allows one argument to be a string
315 class MemberInfoCompare : IComparer {
317 public int Compare (object a, object b)
319 if (a == null || b == null){
320 Console.WriteLine ("Invalid information passed");
321 throw new Exception ();
324 if (a is string)
325 return String.Compare ((string) a, ((MemberInfo)b).Name);
327 if (b is string)
328 return String.Compare (((MemberInfo)a).Name, (string) b);
330 return String.Compare (((MemberInfo)a).Name, ((MemberInfo)b).Name);
334 struct Pair {
335 public object First;
336 public object Second;
338 public Pair (object f, object s)
340 First = f;
341 Second = s;