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