Start
[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                 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                                         return pi [pos].ParameterType;
62                 }
63
64                 public string ParameterName (int pos)
65                 {
66                         if (last_arg_is_params && pos >= pi.Length - 1)
67                                 return pi [pi.Length - 1].Name;
68                         else 
69                                 return pi [pos].Name;
70                 }
71
72                 public string ParameterDesc (int pos)
73                 {
74                         StringBuilder sb = new StringBuilder ();
75
76                         if (pi [pos].IsOut)
77                                 sb.Append ("out ");
78
79                         if (pi [pos].IsIn)
80                                 sb.Append ("in ");
81
82                         if (pos >= pi.Length - 1 && last_arg_is_params)
83                                 sb.Append ("params ");
84                         
85                         sb.Append (TypeManager.MonoBASIC_Name (ParameterType (pos)));
86
87                         return sb.ToString ();
88                         
89                 }
90
91                 public Parameter.Modifier ParameterModifier (int pos)
92                 {
93                         int len = pi.Length;
94                         
95                         if (pos >= len - 1)
96                                 if (last_arg_is_params)
97                                         return Parameter.Modifier.PARAMS;
98                         
99                         Type t = pi [pos].ParameterType;
100                         if (t.IsByRef)
101                                 return Parameter.Modifier.ISBYREF;
102                         
103                         return Parameter.Modifier.NONE;
104                 }
105
106                 public int Count {
107                         get {
108                                 return pi.Length;
109                         }
110                 }
111                 
112         }
113
114         public class InternalParameters : ParameterData {
115                 Type [] param_types;
116
117                 public readonly Parameters Parameters;
118                 
119                 public InternalParameters (Type [] param_types, Parameters parameters)
120                 {
121                         this.param_types = param_types;
122                         this.Parameters = parameters;
123                 }
124
125                 public InternalParameters (DeclSpace ds, Parameters parameters)
126                         : this (parameters.GetParameterInfo (ds), parameters)
127                 {
128                 }
129
130                 public int Count {
131                         get {
132                                 if (param_types == null)
133                                         return 0;
134
135                                 return param_types.Length;
136                         }
137                 }
138
139                 public Type ParameterType (int pos)
140                 {
141                         if (param_types == null)
142                                 return null;
143
144                         Parameter [] fixed_pars = Parameters.FixedParameters;
145                         if (fixed_pars != null){
146                                 int len = fixed_pars.Length;
147                                 if (pos < len)
148                                         return Parameters.FixedParameters [pos].ParameterType;
149                                 else 
150                                         return Parameters.ArrayParameter.ParameterType;
151                         } else
152                                 return Parameters.ArrayParameter.ParameterType;
153                 }
154
155                 public string ParameterName (int pos)
156                 {
157                         Parameter p;
158
159                         if (pos >= Parameters.FixedParameters.Length)
160                                 p = Parameters.ArrayParameter;
161                         else
162                                 p = Parameters.FixedParameters [pos];
163
164                         return p.Name;
165                 }
166
167                 public string ParameterDesc (int pos)
168                 {
169                         string tmp = String.Empty;
170                         Parameter p;
171
172                         if (pos >= Parameters.FixedParameters.Length)
173                                 p = Parameters.ArrayParameter;
174                         else
175                                 p = Parameters.FixedParameters [pos];
176                         
177                         if (p.ModFlags == Parameter.Modifier.REF)
178                                 tmp = "ref ";
179                         else if (p.ModFlags == Parameter.Modifier.OUT)
180                                 tmp = "out ";
181                         else if (p.ModFlags == Parameter.Modifier.PARAMS)
182                                 tmp = "params ";
183
184                         Type t = ParameterType (pos);
185
186                         return tmp + TypeManager.MonoBASIC_Name (t);
187                 }
188
189                 public Parameter.Modifier ParameterModifier (int pos)
190                 {
191                         Parameter.Modifier mod;
192
193                         if (Parameters.FixedParameters == null) {
194                                 if (Parameters.ArrayParameter != null) 
195                                         mod = Parameters.ArrayParameter.ModFlags;
196                                 else
197                                         mod = Parameter.Modifier.NONE;
198                         } else if (pos >= Parameters.FixedParameters.Length)
199                                 mod = Parameters.ArrayParameter.ModFlags;
200                         else
201                                 mod = Parameters.FixedParameters [pos].ModFlags;
202
203                         if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0)
204                                 mod |= Parameter.Modifier.ISBYREF;
205
206                         return mod;
207                 }
208                 
209         }
210
211         class PtrHashtable : Hashtable {
212                 class PtrComparer : IComparer {
213                         public int Compare (object x, object y)
214                         {
215                                 if (x == y)
216                                         return 0;
217                                 else
218                                         return 1;
219                         }
220                 }
221                 
222                 public PtrHashtable ()
223                 {
224                         comparer = new PtrComparer ();
225                         hcp = new CaseInsensitiveHashCodeProvider();
226                 }
227         }
228         
229
230         public class CaseInsensitiveHashtable : Hashtable {
231                 public CaseInsensitiveHashtable() : base()
232                 {
233                         comparer = new CaseInsensitiveComparer();
234                         hcp = new CaseInsensitiveHashCodeProvider();
235                 }
236         }
237
238         //
239         // Compares member infos based on their name and
240         // also allows one argument to be a string
241         //
242         class MemberInfoCompare : IComparer {
243
244                 public int Compare (object a, object b)
245                 {
246                         if (a == null || b == null){
247                                 Console.WriteLine ("Invalid information passed");
248                                 throw new Exception ();
249                         }
250                         
251                         if (a is string)
252                                 return String.Compare ((string) a, ((MemberInfo)b).Name);
253
254                         if (b is string)
255                                 return String.Compare (((MemberInfo)a).Name, (string) b);
256
257                         return String.Compare (((MemberInfo)a).Name, ((MemberInfo)b).Name);
258                 }
259         }
260
261         struct Pair {
262                 public object First;
263                 public object Second;
264                 
265                 public Pair (object f, object s)
266                 {
267                         First = f;
268                         Second = s;
269                 }
270         }
271 }