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