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