2001-12-27 Ravi Pratap <ravi@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
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.GetElementType ();
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)
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                         if (pi [pos].IsOut)
81                                 return Parameter.Modifier.OUT;
82                         
83                         return Parameter.Modifier.NONE;
84                 }
85
86                 public int Count {
87                         get {
88                                 return pi.Length;
89                         }
90                 }
91                 
92         }
93
94         public class InternalParameters : ParameterData {
95                 Type [] param_types;
96
97                 Parameters parameters;
98                 
99                 public InternalParameters (Type [] param_types, Parameters parameters)
100                 {
101                         this.param_types = param_types;
102                         this.parameters = parameters;
103                 }
104
105                 public InternalParameters (TypeContainer tc, Parameters parameters)
106                         : this (parameters.GetParameterInfo (tc), parameters)
107                 {
108                 }
109
110                 public int Count {
111                         get {
112                                 if (param_types == null)
113                                         return 0;
114
115                                 return param_types.Length;
116                         }
117                 }
118
119                 public Type ParameterType (int pos)
120                 {
121                         if (param_types == null)
122                                 return null;
123
124                         int len = parameters.FixedParameters.Length;
125
126                         if (pos < len)
127                                 return parameters.FixedParameters [pos].ParameterType;
128                         else 
129                                 return parameters.ArrayParameter.ParameterType.GetElementType ();
130
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                                 return parameters.FixedParameters [pos].ModFlags;
166                 }
167                 
168         }
169
170         class PtrHashtable : Hashtable {
171                 class PtrComparer : IComparer {
172                         public int Compare (object x, object y)
173                         {
174                                 if (x == y)
175                                         return 0;
176                                 else
177                                         return 1;
178                         }
179                 }
180                 
181                 public PtrHashtable ()
182                 {
183                         comparer = new PtrComparer ();
184                 }
185         }
186
187         //
188         // Compares member infos based on their name and
189         // also allows one argument to be a string
190         //
191         class MemberInfoCompare : IComparer {
192
193                 public int Compare (object a, object b)
194                 {
195                         if (a == null || b == null){
196                                 Console.WriteLine ("Invalid information passed");
197                                 throw new Exception ();
198                         }
199                         
200                         if (a is string)
201                                 return String.Compare ((string) a, ((MemberInfo)b).Name);
202
203                         if (b is string)
204                                 return String.Compare (((MemberInfo)a).Name, (string) b);
205
206                         return String.Compare (((MemberInfo)a).Name, ((MemberInfo)b).Name);
207                 }
208         }
209
210         struct Pair {
211                 public object First;
212                 public object Second;
213                 
214                 public Pair (object f, object s)
215                         {
216                                 First = f;
217                                 Second = s;
218                         }
219         }
220 }