In ilasm/tests:
[mono.git] / mcs / ilasm / codegen / ExternTypeRef.cs
1 //
2 // Mono.ILASM.ExternTypeRef
3 //
4 // Author(s):
5 //  Jackson Harper (Jackson@LatitudeGeo.com)
6 //
7 // (C) 2003 Jackson Harper, All rights reserved
8 //
9
10
11 using System;
12 using System.Collections;
13
14 namespace Mono.ILASM {
15
16         /// <summary>
17         /// A reference to a type in another assembly
18         /// </summary>
19         public class ExternTypeRef : ModifiableType, IClassRef, IScope {
20
21                 private PEAPI.Type type;
22                 private IScope extern_ref;
23                 private string full_name;
24                 private string sig_mod;
25                 private bool is_valuetype;
26
27                 private bool is_resolved;
28
29                 private Hashtable nestedtypes_table;
30                 private Hashtable nestedclass_table;
31                 private Hashtable method_table;
32                 private Hashtable field_table;
33                 private Hashtable p_genericinst_table;
34                 
35                 public ExternTypeRef (IScope extern_ref, string full_name, bool is_valuetype) 
36                         : this (extern_ref, full_name, is_valuetype, null, null)
37                 {
38                 }
39
40                 private ExternTypeRef (IScope extern_ref, string full_name,
41                                 bool is_valuetype, ArrayList conv_list, string sig_mod)
42                 {
43                         this.extern_ref = extern_ref;
44                         this.full_name = full_name;
45                         this.is_valuetype = is_valuetype;
46                         this.sig_mod = sig_mod;
47
48                         nestedclass_table = new Hashtable ();
49                         nestedtypes_table = new Hashtable ();
50                         method_table = new Hashtable ();
51                         field_table = new Hashtable ();
52                         
53                         is_resolved = false;
54                         if (conv_list != null)
55                                 ConversionList = conv_list;
56                 }
57                 
58                 public IClassRef Clone ()
59                 {
60                         return new ExternTypeRef (extern_ref, full_name, is_valuetype, 
61                                         (ArrayList) ConversionList.Clone (), sig_mod);
62                 }
63                 
64                 public GenericTypeInst GetGenericTypeInst (GenericArguments gen_args)
65                 {
66                         return new GenericTypeInst (this, gen_args, is_valuetype);
67                 }
68
69                 public PEAPI.Type ResolveInstance (CodeGen code_gen, GenericArguments gen_args)
70                 {
71                         string sig = gen_args.ToString ();
72                         PEAPI.GenericTypeInst gti = null;
73
74                         if (p_genericinst_table == null)
75                                 p_genericinst_table = new Hashtable ();
76                         else
77                                 gti = p_genericinst_table [sig] as PEAPI.GenericTypeInst;
78
79                         if (gti == null) {
80                                 if (!is_resolved)
81                                         throw new Exception ("Can't ResolveInstance on unresolved ExternTypeRef");
82
83                                 gti = new PEAPI.GenericTypeInst (PeapiType, gen_args.Resolve (code_gen));
84                                 p_genericinst_table [sig] = gti;
85                         }
86
87                         return gti;
88                 }
89
90                 public PEAPI.Type PeapiType {
91                         get { return type; }
92                 }
93
94                 public PEAPI.Class PeapiClass {
95                         get { return type as PEAPI.Class; }
96                 }
97
98                 public string FullName {
99                         get { 
100                                 if (extern_ref == null)
101                                         return full_name + sig_mod;
102                                 else
103                                         return extern_ref.FullName + (extern_ref is ExternTypeRef ? "/" : "") + full_name + sig_mod;
104                         }
105                 }
106
107                 public string Name {
108                         get { return full_name + sig_mod; }
109                 }
110
111                 public override string SigMod {
112                         get { return sig_mod; }
113                         set { sig_mod = value; }
114                 }
115
116                 public IScope ExternRef {
117                         get { return extern_ref; }
118                 }
119
120                 public void Resolve (CodeGen code_gen)
121                 {
122                         if (is_resolved)
123                                 return;
124
125                         ExternTypeRef etr = extern_ref as ExternTypeRef;        
126                         if (etr != null)        
127                                 //This is a nested class, so resolve parent
128                                 etr.Resolve (code_gen);
129
130                         type = extern_ref.GetType (full_name, is_valuetype);
131                         type = Modify (code_gen, type);
132
133                         is_resolved = true;
134                 }
135
136                 public void MakeValueClass ()
137                 {
138                         is_valuetype = true;
139                 }
140
141                 public IMethodRef GetMethodRef (ITypeRef ret_type, PEAPI.CallConv call_conv,
142                                 string name, ITypeRef[] param, int gen_param_count)
143                 {
144                         string sig = MethodDef.CreateSignature (ret_type, name, param, gen_param_count);
145                         ExternMethodRef mr = method_table [sig] as ExternMethodRef;
146                         
147                         if (mr == null) {
148                                 mr = new ExternMethodRef (this, ret_type, call_conv, name, param, gen_param_count);
149                                 method_table [sig] = mr;
150                         }
151
152                         return mr;
153                 }
154
155                 public IFieldRef GetFieldRef (ITypeRef ret_type, string name)
156                 {
157                         ExternFieldRef fr = field_table [name] as ExternFieldRef;
158
159                         if (fr == null) {
160                                 fr = new ExternFieldRef (this, ret_type, name);
161                                 field_table [name] = fr;
162                         }
163
164                         return fr;
165                 }
166
167                 public ExternTypeRef GetTypeRef (string _name, bool is_valuetype)
168                 {
169                         string first= _name;
170                         string rest = "";
171                         int slash = _name.IndexOf ('/');
172
173                         if (slash > 0) {
174                                 first = _name.Substring (0, slash);
175                                 rest = _name.Substring (slash + 1);
176                         }
177
178                         ExternTypeRef ext_typeref = nestedtypes_table [first] as ExternTypeRef;
179                         
180                         if (ext_typeref != null) {
181                                 if (is_valuetype && rest == "")
182                                         ext_typeref.MakeValueClass ();
183                         } else {
184                                 ext_typeref = new ExternTypeRef (this, first, is_valuetype);
185                                 nestedtypes_table [first] = ext_typeref;
186                         }        
187                         
188                         return (rest == "" ? ext_typeref : ext_typeref.GetTypeRef (rest, is_valuetype));
189                 }
190
191                 public PEAPI.IExternRef GetExternTypeRef ()
192                 {
193                         //called by GetType for a nested type
194                         //should this cant be 'modified' type, so it should
195                         //be ClassRef 
196                         return (PEAPI.ClassRef) type;
197                 }
198
199                 public PEAPI.ClassRef GetType (string _name, bool is_valuetype)
200                 {
201                         PEAPI.ClassRef klass = nestedclass_table [_name] as PEAPI.ClassRef;
202                         
203                         if (klass != null)
204                                 return klass;
205
206                         string name_space, name;
207                         ExternTable.GetNameAndNamespace (_name, out name_space, out name);
208
209                         if (is_valuetype)
210                                 klass = (PEAPI.ClassRef) GetExternTypeRef ().AddValueClass (name_space, name);
211                         else        
212                                 klass = (PEAPI.ClassRef) GetExternTypeRef ().AddClass (name_space, name);
213
214                         nestedclass_table [_name] = klass;
215
216                         return klass;
217                 }        
218
219                 public System.Type GetReflectedType ()
220                 {
221                         ExternRef er = extern_ref as ExternRef;
222                         if (er != null) {
223                                 ExternAssembly ea = er as ExternAssembly;
224                                 if (ea != null) {
225                                         System.Reflection.Assembly asm = System.Reflection.Assembly.Load (ea.Name);
226
227                                         //Type name required here, so don't use FullName
228                                         return asm.GetType (Name);
229                                 }/* else ExternModule */
230
231                         } /*else - nested type? */
232                         return null;
233                 }
234         }
235
236 }
237