⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 typesymbol.cs

📁 charp compiler
💻 CS
📖 第 1 页 / 共 5 页
字号:
            m_typeCLR       = clrType;
            m_stFullName    = clrType.FullName;
            m_strName       = clrType.Name;
            m_genre         = GenreFromClrType(clrType);
            m_fIsImported   = true;
            m_fIsInit       = false;
        }

#endregion

#region Compound types (Array, Enum, Delegate)
        // Protected constructor used by Derived TypeEntry to initialize this
        // to a standard type (ex: Array, Enum, Delegate)
        protected TypeEntry(
            ISemanticResolver s, 
            System.Type clrBaseType
            )
        {          
        
            // Common properties
            this.m_fIsImported = false; // @todo - is this right?     
            this.m_genre = Genre.cClass;
            
            // Need to set everything based of the backing type
            if (clrBaseType == typeof(System.Array))
            {   
                Debug.Assert(this.IsArray);
                
                // Must get the CLR type from the provider             
                TypeEntry tArray = s.LookupSystemType("Array");
                
                this.m_scope = tArray.m_scope;
                this.m_interfaces = tArray.m_interfaces;                
                this.m_super = tArray;
                
                this.m_fIsImported = false; // @todo - is this right?
                
                // ClrType will be set in ArrayType's FinalInit()
                this.m_typeCLR = null;
                
                // Not done init yet. Must call FinishArrayInit();
                
            
            } 
            
            else if (clrBaseType == typeof(System.Enum))
            {
                Debug.Assert(this is SymbolEngine.EnumTypeEntry);

                // Must get the CLR type from the provider             
                TypeEntry tEnum = s.LookupSystemType("Enum");
                
                //this.m_scope = tEnum.m_scope;
                this.m_interfaces = tEnum.m_interfaces;
                this.m_super = tEnum;
                                                                
                // ClrType will be set in FinalInit()
                this.m_typeCLR = null;
            }

            else 
            {
                Debug.Assert(false, "Illegal use of TypeEntry ctor");
            }
        }
        
#endregion

        public bool IsInit
        {
            get { return m_fIsInit; }
        }

#endregion
        
#region Other Methods
        public void SetCLRType(ICLRtypeProvider provider)
        {
            m_typeCLR = provider.CreateCLRClass(this);
        }
            
        // Return true if we can assisgn on object of type cFrom to an
        // object of type cTo. Else false. 
        // We should be able to do this w/ System.Type.IsAssignableFrom,
        // but the current implementation is buggy.
        //
        // Implicit conversion if:
        // - cFrom == cTo
        // - cFrom is a derived class of cTo
        // - cTo is a base interface of cFrom   
        // - cFrom is 'null' and cTo is not a value type
        // - cTo is 'Object'
        public static bool IsAssignable(System.Type cFrom, System.Type cTo)
        {
            if (cTo == typeof(object))
                return true;
                
            // @todo - IsValueType the proper check?
            if (cFrom == null && !cTo.IsValueType)
                return true;
            
            if (cFrom == null || cTo == null)
                return false;

            // First strip off References (since we can implicitly assign between
            // refs & values). 
            // Also, we can have T[]& <- T[], so strip refs before matching arrays. 
            // (Note we _can't_ have T&[])
            // If A <- B, then we can assign A <- B&, A& <- B, and A& <- B&. 
            // Codegen will deal with the indirection.
            if (cFrom.IsByRef) 
                cFrom = cFrom.GetElementType();
            
            if (cTo.IsByRef)
                cTo = cTo.GetElementType();
                
            #if false                
            // These are good checks, but we don't have to do them yet...
            // Check pointers
            if (cFrom.IsPointer && !cTo.IsPointer)                
                return false;
            if (!cFrom.IsPointer && cTo.IsPointer)
                return false;
            if (cFrom.IsPointer && cTo.IsPointer)
            {
                cFrom = cFrom.GetElementType();
                cTo = cTo.GetElementType();
                return IsAssignable(cFrom, cTo);
            }
            #endif
                
            // Check for arrays. Note that we can only do real comparisons on non-array
            // types. (ie, compare object references for equality, query for interfaces,
            // etc).
            
            // We can always assign from T[] --> System.Array
            if (cFrom.IsArray && (cTo == typeof(System.Array)))
                return true;
                       
            // If one's an array, and the other's not, then we can't assign
            if (cFrom.IsArray && !cTo.IsArray)
                return false;
            if (!cFrom.IsArray && cTo.IsArray)
                return false;
                
            // Can assign A[] -> B[] if we can assign A->B & the ranks are the same
            if (cFrom.IsArray && cTo.IsArray)
            {
                if (cFrom.GetArrayRank() != cTo.GetArrayRank()) 
                    return false;
                    
                Type cFrom1 = cFrom.GetElementType();
                Type cTo1   = cTo.GetElementType();
                
                bool fOk = IsAssignable(cFrom1, cTo1);                
                return fOk;
            }
            
            // At this point, we're not an array/pointer

            if (cFrom == cTo)
                return true;


            // Check implicit conversions
            if (HasImplicitConversion(cFrom, cTo))
                return true;

            if (cFrom.IsSubclassOf(cTo))
                return true;

            if (SearchInterfaces(cFrom, cTo))
                return true;
            
            return false;
        }
        
        private static bool HasImplicitConversion(System.Type cFrom, System.Type cTo)
        {
            // Check for implicit numeric conversions:
            if (cFrom == typeof(char) && cTo == typeof(int))
                return true;
        
        
            // Check for implicit operator-overload conversions
            return false;
        }
        
        // Helper for IsAssignableFrom
        // Search transitive closure of interfaces
        private static bool SearchInterfaces(System.Type cFrom, System.Type cTo)
        {
            System.Type [] tI = cFrom.GetInterfaces();
            foreach(System.Type t in tI)
            {
                if (t == cTo)
                    return true;
                    
                if (SearchInterfaces(t, cTo))
                    return true;
            }
            
            // check base class
            if (cFrom.BaseType != null)
            {
                if (SearchInterfaces(cFrom.BaseType, cTo))
                    return true;
            }
            
            return false;        
        }

#endregion

#region ILookupController
        
        // Search up the super class chain, base interfaces  
        // Return if found.      
        public SymEntry SmartLookup(string stIdentifier, Scope scope)
        {            
            if (this.IsInterface)
            {
                SymEntry sym = this.MemberScope.LookupSymbolInThisScopeOnly(stIdentifier);
                if (sym != null)
                    return sym;
                    
                Debug.Assert(this.Super == null, "No base class on interface");
                // Check base interfaces
                foreach(TypeEntry ti in BaseInterfaces)
                {
                    sym = ti.SmartLookup(stIdentifier, null);
                    if (sym != null)
                        return sym;
                }            
            } else {            
                TypeEntry tSearch = this;            
                while(tSearch != null)
                {
                    SymEntry sym = tSearch.MemberScope.LookupSymbolInThisScopeOnly(stIdentifier);
                    if (sym != null)
                        return sym;
                    tSearch = tSearch.Super;                    
                }        
            }
            return null;
        }
    
        // Get a node responsible for this scope.
        // For imported types, this will be null
        public AST.Node OwnerNode { 
            get { return this.Node; }
        }
    
        // Get a symbol responsible for this scope. 
        // This may be null. (If this is null, then OwnerNode should not be null).
        public SymEntry OwnerSymbol { 
            get { return this; }
        }
    
        // For debugging purposes. Used by DumpTree();
        public void DumpScope(Scope scope)
        {
            if (this.IsInterface)
            {
                // Interface. No superclass, multiple base classes
                // Have to dump a whole tree here
                Console.Write("->{");
                bool f = false;
                foreach(TypeEntry ti in this.BaseInterfaces)
                {
                    if (f)
                        Console.Write(",");
                    Console.Write(ti.Name);
                    ILookupController p = ti;
                    p.DumpScope(ti.MemberScope); // recursive
                    f = true;                    
                }
                Console.Write("}");
            } else {
                // Class, struct w/ Super class chain.  
                // Just dump a list              
                TypeEntry tSearch = this.Super;            
                while(tSearch != null)
                {
                    Console.Write("->{0}", tSearch.MemberScope.m_szDebugName);
                    tSearch = tSearch.Super;
                }
            }
        }

#endregion

#region Checks
        // Debugging support. Since this is a graph traversal, we need a flag
        // to note if we've already checked this (and prevent an infinite loop)
        protected bool m_fDebugChecked = false;
        public override void DebugCheck(ISemanticResolver s)
        {        
            if (m_fDebugChecked)
                return;

            Debug.Assert(m_fIsInit);
                
            m_fDebugChecked = true; // set flag before the recursion
                
            Debug.Assert(AST.Node.m_DbgAllowNoCLRType || m_typeCLR != null);
            
            if (Node != null)
            {
                Debug.Assert(Node.Symbol == this);                
            }
            
            // Scope can be null (if we're not resolved)
            if (m_scope != null) 
            {                   
                m_scope.DebugCheck(s);            
            }            
        }
        
        // Write out this Entry's name, attributes, (and if fRecursive, then nested scope too)
        public override void Dump(XmlWriter o, bool fRecursive)
        {
            o.WriteStartElement("TypeEntry");
            o.WriteAttributeString("name", this.m_strName);
            if (fRecursive && (m_scope != null)) 
            {
                m_scope.Dump(o, true);
            }
            o.WriteEndElement();        
        }
#endregion


#region Properties and Data

        static readonly TypeEntry [] m_emptyinterfaces = new TypeEntry[0];
        // Attributes on this type.
        // @todo - use reflection's attributes or our own?
        //        System.Reflection.TypeAttributes m_attrs = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -