2006-11-14 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / ilasm / codegen / ExternTypeRef.cs
index e21510302e57cba1abd0a4a9bdce02998a405fa1..1480a024115c0cd4744fdb8983cb4279a94e58c1 100644 (file)
 
 
 using System;
+using System.Collections;
 
 namespace Mono.ILASM {
 
         /// <summary>
         /// A reference to a type in another assembly
         /// </summary>
-        public class ExternTypeRef : ModifiableType, IClassRef {
-
-                private PEAPI.Type type;
-                private string assembly_name;
-                private string full_name;
-               private bool is_valuetype;
+        public class ExternTypeRef : BaseClassRef , IScope {
+
+                private IScope extern_ref;
+                private Hashtable nestedtypes_table;
+                private Hashtable nestedclass_table;
+                
+                public ExternTypeRef (IScope extern_ref, string full_name, bool is_valuetype) 
+                        : this (extern_ref, full_name, is_valuetype, null, null)
+                {
+                }
 
-               private bool is_resolved;
+                private ExternTypeRef (IScope extern_ref, string full_name,
+                                bool is_valuetype, ArrayList conv_list, string sig_mod)
+                       : base (full_name, is_valuetype, conv_list, sig_mod)
+                {
+                        this.extern_ref = extern_ref;
 
-                public ExternTypeRef (string assembly_name, string full_name, bool is_valuetype)
+                        nestedclass_table = new Hashtable ();
+                        nestedtypes_table = new Hashtable ();
+                }
+                
+                public override BaseClassRef Clone ()
                 {
-                        this.assembly_name = assembly_name;
-                        this.full_name = full_name;
-                       this.is_valuetype = is_valuetype;               
-       
-                       is_resolved = false;
+                        return new ExternTypeRef (extern_ref, full_name, is_valuetype, 
+                                        (ArrayList) ConversionList.Clone (), sig_mod);
                 }
 
-                public PEAPI.Type PeapiType {
-                        get { return type; }
+                public override string FullName {
+                        get { 
+                                if (extern_ref == null)
+                                        return full_name + sig_mod;
+                                else
+                                        return extern_ref.FullName + (extern_ref is ExternTypeRef ? "/" : "") + full_name + sig_mod;
+                        }
                 }
 
-               public PEAPI.Class PeapiClass {
-                        get { return type as PEAPI.Class; }
+                public string Name {
+                        get { return full_name + sig_mod; }
                 }
 
-                public string FullName {
-                        get { return full_name; }
+                public IScope ExternRef {
+                        get { return extern_ref; }
                 }
 
-                public void Resolve (CodeGen code_gen)
+                public override void Resolve (CodeGen code_gen)
                 {
-                       if (is_resolved)
-                               return;
+                        if (is_resolved)
+                                return;
 
-                       if (is_valuetype)
-                               type = code_gen.ExternTable.GetValueClass (assembly_name, full_name);
-                       else
-                               type = code_gen.ExternTable.GetClass (assembly_name, full_name);
+                        ExternTypeRef etr = extern_ref as ExternTypeRef;        
+                        if (etr != null)        
+                                //This is a nested class, so resolve parent
+                                etr.Resolve (code_gen);
 
-                        type = Modify (code_gen, type, ref full_name);
+                        type = extern_ref.GetType (full_name, is_valuetype);
+                        type = Modify (code_gen, type);
 
-                       is_resolved = true;
+                        is_resolved = true;
                 }
 
-               public void MakeValueClass ()
-               {
-                       is_valuetype = true;
-               }
-
-                public IMethodRef GetMethodRef (ITypeRef ret_type, PEAPI.CallConv call_conv,
-                                string name, ITypeRef[] param)
+                protected override BaseMethodRef CreateMethodRef (BaseTypeRef ret_type, PEAPI.CallConv call_conv,
+                                string name, BaseTypeRef[] param, int gen_param_count)
                 {
-                        return new ExternMethodRef (this, ret_type, call_conv, name, param);
+                        return new ExternMethodRef (this, ret_type, call_conv, name, param, gen_param_count);
                 }
 
-                public IFieldRef GetFieldRef (ITypeRef ret_type, string name)
+                protected override IFieldRef CreateFieldRef (BaseTypeRef ret_type, string name)
                 {
                         return new ExternFieldRef (this, ret_type, name);
                 }
 
-                public IClassRef AsClassRef (CodeGen code_gen)
+                public ExternTypeRef GetTypeRef (string _name, bool is_valuetype)
+                {
+                        string first= _name;
+                        string rest = "";
+                        int slash = _name.IndexOf ('/');
+
+                        if (slash > 0) {
+                                first = _name.Substring (0, slash);
+                                rest = _name.Substring (slash + 1);
+                        }
+
+                        ExternTypeRef ext_typeref = nestedtypes_table [first] as ExternTypeRef;
+                        
+                        if (ext_typeref != null) {
+                                if (is_valuetype && rest == "")
+                                        ext_typeref.MakeValueClass ();
+                        } else {
+                                ext_typeref = new ExternTypeRef (this, first, is_valuetype);
+                                nestedtypes_table [first] = ext_typeref;
+                        }        
+                        
+                        return (rest == "" ? ext_typeref : ext_typeref.GetTypeRef (rest, is_valuetype));
+                }
+
+                public PEAPI.IExternRef GetExternTypeRef ()
+                {
+                        //called by GetType for a nested type
+                        //should this cant be 'modified' type, so it should
+                        //be ClassRef 
+                        return (PEAPI.ClassRef) type;
+                }
+
+                public PEAPI.ClassRef GetType (string _name, bool is_valuetype)
+                {
+                        PEAPI.ClassRef klass = nestedclass_table [_name] as PEAPI.ClassRef;
+                        
+                        if (klass != null)
+                                return klass;
+
+                        string name_space, name;
+                        ExternTable.GetNameAndNamespace (_name, out name_space, out name);
+
+                        if (is_valuetype)
+                                klass = (PEAPI.ClassRef) GetExternTypeRef ().AddValueClass (name_space, name);
+                        else        
+                                klass = (PEAPI.ClassRef) GetExternTypeRef ().AddClass (name_space, name);
+
+                        nestedclass_table [_name] = klass;
+
+                        return klass;
+                }        
+
+                public System.Type GetReflectedType ()
                 {
-                        throw new NotImplementedException ("Not implemented.");
+                        ExternRef er = extern_ref as ExternRef;
+                        if (er != null) {
+                                ExternAssembly ea = er as ExternAssembly;
+                                if (ea != null) {
+                                        System.Reflection.Assembly asm = System.Reflection.Assembly.Load (ea.Name);
+
+                                        //Type name required here, so don't use FullName
+                                        return asm.GetType (Name);
+                                }/* else ExternModule */
+
+                        } /*else - nested type? */
+                        return null;
                 }
         }