a8939164e2906acd8923aa6af74b45d12ba00ef0
[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
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                         //
175                         // We need to and for REF/OUT, because if either is set the
176                         // extra flag ISBYREF will be set as well
177                         //
178                         if ((p.ModFlags & Parameter.Modifier.REF) != 0)
179                                 tmp = "ref ";
180                         else if ((p.ModFlags & Parameter.Modifier.OUT) != 0)
181                                 tmp = "out ";
182                         else if (p.ModFlags == Parameter.Modifier.PARAMS)
183                                 tmp = "params ";
184
185                         Type t = ParameterType (pos);
186
187                         return tmp + TypeManager.CSharpName (t);
188                 }
189
190                 public Parameter.Modifier ParameterModifier (int pos)
191                 {
192                         Parameter.Modifier mod;
193
194                         if (Parameters.FixedParameters == null) {
195                                 if (Parameters.ArrayParameter != null) 
196                                         mod = Parameters.ArrayParameter.ModFlags;
197                                 else
198                                         mod = Parameter.Modifier.NONE;
199                         } else if (pos >= Parameters.FixedParameters.Length)
200                                 mod = Parameters.ArrayParameter.ModFlags;
201                         else
202                                 mod = Parameters.FixedParameters [pos].ModFlags;
203
204                         if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0)
205                                 mod |= Parameter.Modifier.ISBYREF;
206
207                         return mod;
208                 }
209                 
210         }
211
212         class PtrHashtable : Hashtable {
213                 class PtrComparer : IComparer {
214                         public int Compare (object x, object y)
215                         {
216                                 if (x == y)
217                                         return 0;
218                                 else
219                                         return 1;
220                         }
221                 }
222                 
223                 public PtrHashtable ()
224                 {
225                         comparer = new PtrComparer ();
226                 }
227         }
228
229         //
230         // Compares member infos based on their name and
231         // also allows one argument to be a string
232         //
233         class MemberInfoCompare : IComparer {
234
235                 public int Compare (object a, object b)
236                 {
237                         if (a == null || b == null){
238                                 Console.WriteLine ("Invalid information passed");
239                                 throw new Exception ();
240                         }
241                         
242                         if (a is string)
243                                 return String.Compare ((string) a, ((MemberInfo)b).Name);
244
245                         if (b is string)
246                                 return String.Compare (((MemberInfo)a).Name, (string) b);
247
248                         return String.Compare (((MemberInfo)a).Name, ((MemberInfo)b).Name);
249                 }
250         }
251
252         struct Pair {
253                 public object First;
254                 public object Second;
255                 
256                 public Pair (object f, object s)
257                 {
258                         First = f;
259                         Second = s;
260                 }
261         }
262 }