Ooops. No wonder people complained I never fixed this, I never flushed
[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
17 namespace Mono.CSharp {
18
19         public interface ParameterData {
20                 Type ParameterType (int pos);
21                 int  Count { get; }
22                 string ParameterDesc (int pos);
23                 Parameter.Modifier ParameterModifier (int pos);
24         }
25
26         public class ReflectionParameters : ParameterData {
27                 ParameterInfo [] pi;
28                 bool last_arg_is_params = false;
29                 
30                 public ReflectionParameters (ParameterInfo [] pi)
31                 {
32                         object [] attrs;
33                         
34                         this.pi = pi;
35
36                         int count = pi.Length-1;
37
38                         if (count >= 0) {
39                                 attrs = pi [count].GetCustomAttributes (TypeManager.param_array_type, true);
40
41                                 if (attrs == null)
42                                         return;
43                                 
44                                 if (attrs.Length == 0)
45                                         return;
46
47                                 last_arg_is_params = true;
48                         }
49                 }
50                        
51                 public Type ParameterType (int pos)
52                 {
53                         if (last_arg_is_params && pos >= pi.Length - 1)
54                                 return pi [pi.Length - 1].ParameterType;
55                         else 
56                                 return pi [pos].ParameterType;
57                 }
58
59                 public string ParameterDesc (int pos)
60                 {
61                         StringBuilder sb = new StringBuilder ();
62
63                         if (pi [pos].IsOut)
64                                 sb.Append ("out ");
65
66                         if (pi [pos].IsIn)
67                                 sb.Append ("in ");
68
69                         if (pos >= pi.Length - 1 && last_arg_is_params)
70                                 sb.Append ("params ");
71                         
72                         sb.Append (TypeManager.CSharpName (ParameterType (pos)));
73
74                         return sb.ToString ();
75                         
76                 }
77
78                 public Parameter.Modifier ParameterModifier (int pos)
79                 {
80                         int len = pi.Length;
81                         
82                         if (pos >= len - 1)
83                                 if (last_arg_is_params)
84                                         return Parameter.Modifier.PARAMS;
85                         
86                         Type t = pi [pos].ParameterType;
87                         if (t.IsByRef)
88                                 return Parameter.Modifier.OUT;
89                         
90                         return Parameter.Modifier.NONE;
91                 }
92
93                 public int Count {
94                         get {
95                                 return pi.Length;
96                         }
97                 }
98                 
99         }
100
101         public class InternalParameters : ParameterData {
102                 Type [] param_types;
103
104                 Parameters parameters;
105                 
106                 public InternalParameters (Type [] param_types, Parameters parameters)
107                 {
108                         this.param_types = param_types;
109                         this.parameters = parameters;
110                 }
111
112                 public InternalParameters (DeclSpace ds, Parameters parameters)
113                         : this (parameters.GetParameterInfo (ds), parameters)
114                 {
115                 }
116
117                 public int Count {
118                         get {
119                                 if (param_types == null)
120                                         return 0;
121
122                                 return param_types.Length;
123                         }
124                 }
125
126                 public Type ParameterType (int pos)
127                 {
128                         if (param_types == null)
129                                 return null;
130
131                         Parameter [] fixed_pars = parameters.FixedParameters;
132                         if (fixed_pars != null){
133                                 int len = fixed_pars.Length;
134                                 if (pos < len)
135                                         return parameters.FixedParameters [pos].ParameterType;
136                                 else 
137                                         return parameters.ArrayParameter.ParameterType;
138                         } else
139                                 return parameters.ArrayParameter.ParameterType;
140                 }
141
142                 public string ParameterDesc (int pos)
143                 {
144                         string tmp = String.Empty;
145                         Parameter p;
146
147                         if (pos >= parameters.FixedParameters.Length)
148                                 p = parameters.ArrayParameter;
149                         else
150                                 p = parameters.FixedParameters [pos];
151                         
152                         if (p.ModFlags == Parameter.Modifier.REF)
153                                 tmp = "ref ";
154                         else if (p.ModFlags == Parameter.Modifier.OUT)
155                                 tmp = "out ";
156                         else if (p.ModFlags == Parameter.Modifier.PARAMS)
157                                 tmp = "params ";
158
159                         Type t = ParameterType (pos);
160
161                         return tmp + TypeManager.CSharpName (t);
162                 }
163
164                 public Parameter.Modifier ParameterModifier (int pos)
165                 {
166                         if (parameters.FixedParameters == null) {
167                                 if (parameters.ArrayParameter != null) 
168                                         return parameters.ArrayParameter.ModFlags;
169                                 else
170                                         return Parameter.Modifier.NONE;
171                         }
172                         
173                         if (pos >= parameters.FixedParameters.Length)
174                                 return parameters.ArrayParameter.ModFlags;
175                         else {
176                                 Parameter.Modifier m = parameters.FixedParameters [pos].ModFlags;
177
178                                 //
179                                 // We use a return value of "OUT" for "reference" parameters.
180                                 // both out and ref flags in the source map to reference parameters.
181                                 //
182                                 if (m == Parameter.Modifier.OUT || m == Parameter.Modifier.REF)
183                                         return Parameter.Modifier.OUT;
184                                 
185                                 return Parameter.Modifier.NONE;
186                         }
187                 }
188                 
189         }
190
191         class PtrHashtable : Hashtable {
192                 class PtrComparer : IComparer {
193                         public int Compare (object x, object y)
194                         {
195                                 if (x == y)
196                                         return 0;
197                                 else
198                                         return 1;
199                         }
200                 }
201                 
202                 public PtrHashtable ()
203                 {
204                         comparer = new PtrComparer ();
205                 }
206         }
207
208         //
209         // Compares member infos based on their name and
210         // also allows one argument to be a string
211         //
212         class MemberInfoCompare : IComparer {
213
214                 public int Compare (object a, object b)
215                 {
216                         if (a == null || b == null){
217                                 Console.WriteLine ("Invalid information passed");
218                                 throw new Exception ();
219                         }
220                         
221                         if (a is string)
222                                 return String.Compare ((string) a, ((MemberInfo)b).Name);
223
224                         if (b is string)
225                                 return String.Compare (((MemberInfo)a).Name, (string) b);
226
227                         return String.Compare (((MemberInfo)a).Name, ((MemberInfo)b).Name);
228                 }
229         }
230
231         struct Pair {
232                 public object First;
233                 public object Second;
234                 
235                 public Pair (object f, object s)
236                 {
237                         First = f;
238                         Second = s;
239                 }
240         }
241 }