Merge pull request #4246 from Unity-Technologies/mcs-generic-constraint-enumerator
[mono.git] / mcs / ilasm / codegen / ExternTypeRef.cs
index a697797121fd420aba49a005f9f9f907553e3a98..1e4d01d0cf8293cee012b369113866586213d64f 100644 (file)
@@ -16,111 +16,143 @@ namespace Mono.ILASM {
         /// <summary>
         /// A reference to a type in another assembly
         /// </summary>
-        public class ExternTypeRef : ModifiableType, IClassRef {
+        public class ExternTypeRef : BaseClassRef , IScope {
 
-                private PEAPI.Type type;
-                private ExternRef extern_ref;
-                private string full_name;
-                private string sig_mod;
-                private bool is_valuetype;
-                private ExternTable extern_table;
-
-                private bool is_resolved;
-
-                private Hashtable method_table;
-                private Hashtable field_table;
+                private IScope extern_ref;
+                private Hashtable nestedtypes_table;
+                private Hashtable nestedclass_table;
                 
-                public ExternTypeRef (ExternRef extern_ref, string full_name,
-                                bool is_valuetype, ExternTable extern_table)
+                public ExternTypeRef (IScope extern_ref, string full_name, bool is_valuetype) 
+                        : this (extern_ref, full_name, is_valuetype, null, null)
                 {
-                        this.extern_ref = extern_ref;
-                        this.full_name = full_name;
-                        this.is_valuetype = is_valuetype;
-                        this.extern_table = extern_table;
-                        sig_mod = String.Empty;
-
-                        method_table = new Hashtable ();
-                        field_table = new Hashtable ();
-                        
-                        is_resolved = false;
                 }
 
-                private ExternTypeRef (ExternRef extern_ref, string full_name,
-                                bool is_valuetype, ExternTable extern_table,
-                                ArrayList conv_list) : this (extern_ref, full_name,
-                                                is_valuetype, extern_table)
+                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)
                 {
-                        ConversionList = conv_list;
+                        this.extern_ref = extern_ref;
+
+                        nestedclass_table = new Hashtable ();
+                        nestedtypes_table = new Hashtable ();
                 }
                 
-                public ExternTypeRef Clone ()
+                public override BaseTypeRef Clone ()
                 {
-                        return new ExternTypeRef (extern_ref, FullName, is_valuetype,
-                                        extern_table, (ArrayList) ConversionList.Clone ());
-                }
-                
-                public PEAPI.Type PeapiType {
-                        get { return type; }
+                        return new ExternTypeRef (extern_ref, full_name, is_valuetype, 
+                                        (ArrayList) ConversionList.Clone (), sig_mod);
                 }
 
-                public PEAPI.Class PeapiClass {
-                        get { return type as PEAPI.Class; }
+                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 string FullName {
+                public string Name {
                         get { return full_name + sig_mod; }
                 }
 
-
-                public override string SigMod {
-                        get { return sig_mod; }
-                        set { sig_mod = value; }
+                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_valuetype)
-                                type = extern_ref.GetValueType (full_name);
-                        else
-                                type = extern_ref.GetType (full_name);
+                        ExternTypeRef etr = extern_ref as ExternTypeRef;        
+                        if (etr != null)        
+                                //This is a nested class, so resolve parent
+                                etr.Resolve (code_gen);
 
+                        type = extern_ref.GetType (full_name, is_valuetype);
                         type = Modify (code_gen, type);
 
                         is_resolved = true;
                 }
 
-                public void MakeValueClass ()
+                protected override BaseMethodRef CreateMethodRef (BaseTypeRef ret_type, PEAPI.CallConv call_conv,
+                                string name, BaseTypeRef[] param, int gen_param_count)
                 {
-                        is_valuetype = true;
+                        return new ExternMethodRef (this, ret_type, call_conv, name, param, gen_param_count);
                 }
 
-                public IMethodRef GetMethodRef (ITypeRef ret_type, PEAPI.CallConv call_conv,
-                                string name, ITypeRef[] param)
+                protected override IFieldRef CreateFieldRef (BaseTypeRef ret_type, string name)
                 {
-                        string sig = MethodDef.CreateSignature (name, param);
-                        ExternMethodRef mr = method_table [sig] as ExternMethodRef;
-                        
-                        if (mr == null) {
-                                mr = new ExternMethodRef (this, ret_type, call_conv, name, param);
-                                method_table [sig] = mr;
+                        return new ExternFieldRef (this, ret_type, name);
+                }
+
+                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);
                         }
 
-                        return mr;
+                        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 IFieldRef GetFieldRef (ITypeRef ret_type, string name)
+                public PEAPI.IExternRef GetExternTypeRef ()
                 {
-                        ExternFieldRef fr = field_table [name] as ExternFieldRef;
+                        //called by GetType for a nested type
+                        //should this cant be 'modified' type, so it should
+                        //be ClassRef 
+                        return (PEAPI.ClassRef) type;
+                }
 
-                        if (fr == null) {
-                                fr = new ExternFieldRef (this, ret_type, name);
-                                field_table [name] = fr;
-                        }
+                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);
 
-                        return fr;
+                        nestedclass_table [_name] = klass;
+
+                        return klass;
+                }        
+
+                public System.Type GetReflectedType ()
+                {
+                        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;
                 }
         }