c860a579583581c7c270c3d24695f9e54b114794
[mono.git] / 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                 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
38                         int count = pi.Length-1;
39
40                         if (count >= 0) {
41                                 attrs = pi [count].GetCustomAttributes (TypeManager.param_array_type, true);
42
43                                 if (attrs == null)
44                                         return;
45                                 
46                                 if (attrs.Length == 0)
47                                         return;
48
49                                 last_arg_is_params = true;
50                         }
51                 }
52                        
53                 public Type ParameterType (int pos)
54                 {
55                         if (last_arg_is_params && pos >= pi.Length - 1)
56                                 return pi [pi.Length - 1].ParameterType;
57                         else
58                                 if (pos >= pi.Length)
59                                         return null;
60                                 else {
61                                         Type pt = pi [pos].ParameterType;
62                                         if (pt.IsByRef)
63                                                 pt = pt.GetElementType();
64                                         return pt;
65                                 }
66                 }
67
68                 public string ParameterName (int pos)
69                 {
70                         if (last_arg_is_params && pos >= pi.Length - 1)
71                                 return pi [pi.Length - 1].Name;
72                         else 
73                                 return pi [pos].Name;
74                 }
75
76                 public string ParameterDesc (int pos)
77                 {
78                         StringBuilder sb = new StringBuilder ();
79
80                         if (pi [pos].IsOut)
81                                 sb.Append ("out ");
82
83                         if (pi [pos].IsIn)
84                                 sb.Append ("in ");
85
86                         if (pos >= pi.Length - 1 && last_arg_is_params)
87                                 sb.Append ("params ");
88                         
89                         sb.Append (TypeManager.MonoBASIC_Name (ParameterType (pos)));
90
91                         return sb.ToString ();
92                         
93                 }
94
95                 public Parameter.Modifier ParameterModifier (int pos)
96                 {
97                         int len = pi.Length;
98                         
99                         if (pos >= len - 1)
100                                 if (last_arg_is_params)
101                                         return Parameter.Modifier.PARAMS;
102                         
103                         Type t = pi [pos].ParameterType;
104                         if (t.IsByRef)
105                                 return Parameter.Modifier.ISBYREF | Parameter.Modifier.REF;
106                         
107                         return Parameter.Modifier.NONE;
108                 }
109
110                 public int Count {
111                         get {
112                                 return pi.Length;
113                         }
114                 }
115                 
116         }
117
118         public class InternalParameters : ParameterData {
119                 Type [] param_types;
120
121                 public readonly Parameters Parameters;
122                 
123                 public InternalParameters (Type [] param_types, Parameters parameters)
124                 {
125                         this.param_types = param_types;
126                         this.Parameters = parameters;
127                 }
128
129                 public InternalParameters (DeclSpace ds, Parameters parameters)
130                         : this (parameters.GetParameterInfo (ds), parameters)
131                 {
132                 }
133
134                 public int Count {
135                         get {
136                                 if (param_types == null)
137                                         return 0;
138
139                                 return param_types.Length;
140                         }
141                 }
142
143                 public Type ParameterType (int pos)
144                 {
145                         if (param_types == null)
146                                 return null;
147
148                         Parameter [] fixed_pars = Parameters.FixedParameters;
149                         if (fixed_pars != null){
150                                 int len = fixed_pars.Length;
151                                 if (pos < len)
152                                         return Parameters.FixedParameters [pos].ParameterType;
153                                 else 
154                                         return Parameters.ArrayParameter.ParameterType;
155                         } else
156                                 return Parameters.ArrayParameter.ParameterType;
157                 }
158
159                 public string ParameterName (int pos)
160                 {
161                         Parameter p;
162
163                         if (pos >= Parameters.FixedParameters.Length)
164                                 p = Parameters.ArrayParameter;
165                         else
166                                 p = Parameters.FixedParameters [pos];
167
168                         return p.Name;
169                 }
170
171                 public string ParameterDesc (int pos)
172                 {
173                         string tmp = String.Empty;
174                         Parameter p;
175
176                         if (pos >= Parameters.FixedParameters.Length)
177                                 p = Parameters.ArrayParameter;
178                         else
179                                 p = Parameters.FixedParameters [pos];
180                         
181                         if (p.ModFlags == Parameter.Modifier.REF)
182                                 tmp = "ref ";
183                         else if (p.ModFlags == Parameter.Modifier.OUT)
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.MonoBASIC_Name (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                         hcp = new CaseInsensitiveHashCodeProvider();
230                 }
231         }
232         
233
234         public class CaseInsensitiveHashtable : Hashtable {
235                 public CaseInsensitiveHashtable() : base()
236                 {
237                         comparer = new CaseInsensitiveComparer();
238                         hcp = new CaseInsensitiveHashCodeProvider();
239                 }
240         }
241
242         //
243         // Compares member infos based on their name and
244         // also allows one argument to be a string
245         //
246         class MemberInfoCompare : IComparer {
247
248                 public int Compare (object a, object b)
249                 {
250                         if (a == null || b == null){
251                                 Console.WriteLine ("Invalid information passed");
252                                 throw new Exception ();
253                         }
254                         
255                         if (a is string)
256                                 return String.Compare ((string) a, ((MemberInfo)b).Name);
257
258                         if (b is string)
259                                 return String.Compare (((MemberInfo)a).Name, (string) b);
260
261                         return String.Compare (((MemberInfo)a).Name, ((MemberInfo)b).Name);
262                 }
263         }
264
265         struct Pair {
266                 public object First;
267                 public object Second;
268                 
269                 public Pair (object f, object s)
270                 {
271                         First = f;
272                         Second = s;
273                 }
274         }
275 }