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