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

📄 typesymbol.cs

📁 charp compiler
💻 CS
📖 第 1 页 / 共 5 页
字号:
                    int j;
                    for(j = i; j < alParamTypes.Length; j++)
                    {
                        System.Type tDerived = alParamTypes[j];
                    
                            
                        string stBase = tBase.ToString();                    
                        string stDerived = (tDerived == null) ? "null" : tDerived.ToString();
                    
                        //if ((tBase != tDerived) && !tDerived.IsSubclassOf(tBase))
                        if (!SymbolEngine.TypeEntry.IsAssignable(tDerived, tBase))
                            break;
                    }

                    if (j == alParamTypes.Length)
                    {
                        info.AddVarargMatch(mDecl);
                    }
                }
            } // end vararg
        } // end AddIfParamsMatch
            

        // Helper. Lookup the method in the specific scope
        // Add all matches to the info object        
        protected void SearchForOverloadedMethodInScope(
            Scope scope,
            ISemanticResolver s, 
            string stName, 
            System.Type [] alParamTypes,
            OverloadedErrorInfo info
            )
        {
            // Find header. If no no header, then the method isn't in this scope
            MethodHeaderEntry header = (MethodHeaderEntry) scope.LookupSymbolInThisScopeOnly(m_stMethodHeaderPrefix + stName);
            
            //MethodHeaderEntry header = LookupMethodHeader(stName);
            if (header == null)
                return;
                                                            
            // Now, traverse list of methods finding an appropriate match            
            foreach(MethodExpEntry m in header)
            {
                Debug.Assert(m.Name == stName);
                if (m.IsOverride)
                    continue;
                string stDecorated = TypeEntry.GetDecoratedParams(m); // debug helper
                AddIfParamsMatch(alParamTypes, m, info);
            }
                                    
        }

        // Helper:
        // Search for a method in the given class (and all of its super classes)
        // Even if we get the method from an interface, it still must be implemented in 
        // the super-class chain, so just searching that will be sufficient.
        // We don't have to search the entire interface tree.
        protected void LookupMethodInClass(
            ISemanticResolver s, 
            string stName, 
            Type [] alParamTypes,
            OverloadedErrorInfo info
            )
        {
            Debug.Assert(IsClass || IsStruct || IsRef);
            
            this.EnsureResolved(s);
            
            // Make life really easy be doing a broad search for the method header
            // If we don't find that, we won't find any overload / exact match            
            //MethodHeaderEntry header = (MethodHeaderEntry) m_scope.LookupSymbol(m_stMethodHeaderPrefix + stName);
            MethodHeaderEntry header = LookupMethodHeader(stName);
            if (header == null)
            {
                info.SetNoHeader();
                return ;
            }
            
            
            string stDecorated = GetDecoratedParams(stName, alParamTypes);
            MethodExpEntry sym = null;
            
            // Must resolve a member function (Specified by name & param types) to a symbol.
            // A function call may match multiple symbols. Ex:
            //      class Foo { int f(Base); int f(Derived); }
            // Now Foo.f(Derive) technically matches both versions of f; but there's not 
            // really any ambiguity. So....
            // 1) First try for an exact match.
            // 2) Else if we don't have an exact match, then we have to do a more 
            // thorough search based off matching parameter types.
            sym = (MethodExpEntry) s.LookupSymbol(m_scope, stDecorated, false);
                
            if (sym != null)
            {
                info.AddMatch(sym);
                return;
            }
            
            
            // @hack - strip all refs and try again...
            // @todo - need to properly implement the notion of 'best match'
            // because int& --> { int, object }, it should match with object.
            {
                System.Type [] alParamTypes2 = new System.Type[alParamTypes.Length];
                for(int i = 0; i < alParamTypes2.Length; i++)
                {
                    alParamTypes2[i] = alParamTypes[i];
                    if ((alParamTypes2[i] != null) && alParamTypes2[i].IsByRef)
                        alParamTypes2[i] = alParamTypes2[i].GetElementType();
                }
                string stDecorated2 = GetDecoratedParams(stName, alParamTypes2);
                sym = (MethodExpEntry) s.LookupSymbol(m_scope, stDecorated2, false);
                    
                if (sym != null)
                {
                    info.AddMatch(sym);
                    return;
                }
            }
            
            // No exact match found, so do a search:
            // Look at each scope in the super-class chain
            #if true            
            Scope oldScope = null;
            for(TypeEntry tSearch = this; tSearch != null; tSearch = tSearch.Super)
            {
                // @todo -major hack. T[] copies scope from System.Array. 
                // Traversing scopes was ok (since T[]'s --> System.Object, 2 links)
                // But traversing by class is not (since T[]'s --> S.Array --> S.Object, 3 links)
                // So any array member lookup happens in the same scope twice.
                if (oldScope == tSearch.MemberScope)
                    continue;
                
                oldScope = tSearch.MemberScope;
                
                // In each scope, search all of the methods for a match                
                SearchForOverloadedMethodInScope(tSearch.MemberScope, s, stName, alParamTypes, info);                
            }
            #else            
            for(Scope scope = m_scope; scope != null; scope = scope.InheritedParent)
            {
                // In each scope, search all of the methods for a match
                SearchForOverloadedMethodInScope(scope, s, stName, alParamTypes, info);                
            }
            #endif
             
        }

#endregion Internal Lookup helpers

#region Public Lookup functions
        // Use for inheritence /debug checks.
        // return null if not found.
        public MethodExpEntry LookupExactMethod(MethodExpEntry m)
        {
            string stDecorated = GetDecoratedParams(m);
            return (MethodExpEntry) m_scope.LookupSymbol(stDecorated);
        }

        // Given an undecorated method name, get the header. Used when we want to
        // search through a scope by method name and we don't know the parameters
        // This is like the inverse of LookupIndexer (in which case we know the
        // parameters, but don't know the name)
        // Return null if not found.
        public MethodHeaderEntry  LookupMethodHeader(string stMethodName)
        {
            MethodHeaderEntry header = (MethodHeaderEntry) m_scope.LookupSymbol(m_stMethodHeaderPrefix + stMethodName);
            return header;
        }

        // Given a method defined in an interface, look it up in the current class
        // We search for an exact match.
        // Return null if not found.
        public MethodExpEntry LookupInterfaceMethod(MethodExpEntry mInterface, bool fLookInSuperClass)
        {
            Debug.Assert(this.IsClass || this.IsStruct);
            Debug.Assert(mInterface.SymbolClass.IsInterface);
            
            string stDecorated = GetDecoratedParams(mInterface);
            
            if (!fLookInSuperClass)
            {
                SymEntry sym = m_scope.LookupSymbolInThisScopeOnly(stDecorated);
                if (sym == null)
                    return null;
                Debug.Assert(sym is MethodExpEntry);
                return sym as MethodExpEntry;                    
            }
            
            // Search all class & superclasses for an exact match
            //for(Scope scope = m_scope; scope != null; scope = scope.InheritedParent)
            for(TypeEntry tSearch = this; tSearch != null; tSearch = tSearch.Super)
            {
                Scope scope = tSearch.MemberScope;
                
                SymEntry sym = scope.LookupSymbolInThisScopeOnly(stDecorated);
                if (sym != null)
                {
                    Debug.Assert(sym is MethodExpEntry);                
                    return sym as MethodExpEntry;                    
                }
            }
            
            return null;
        }

        // Find an indexer. Throw an exception if not found.
        // Indexers are recognized by Parameter type & if they're a get/set
        public MethodExpEntry LookupIndexer(
            FileRange location,
            ISemanticResolver s,
            Type [] alParamTypes, // includes the value for set_X methods
            bool fIsLeft // true for set_X, false for get_X
            )
        {
            OverloadedErrorInfo info = new OverloadedErrorInfo();
            
            // Unfortunately, we don't have the name. We can only match on signature.
            for(Scope scope = m_scope; scope != null; scope = scope.m_LexicalParent)
            {
                // In each scope, search all of the methods for a match
                foreach(SymEntry sym in scope)
                {
                    MethodExpEntry m = sym as MethodExpEntry;
                    if (m != null)
                    {
                        // Indexers have special name bit set.
                        if (m.Info.IsSpecialName && !m.IsCtor) 
                        {
                            // Still have to discriminate between an indexer & a set property
                            string stName = m.Name;
                            if (fIsLeft && !stName.StartsWith("set_"))
                                continue;                                            
                            if (!fIsLeft && !stName.StartsWith("get_"))
                                continue;
                                                    
                            this.AddIfParamsMatch(alParamTypes, m, info);
                        }
                    }
                } // foreach symentry                
            } // foreach scope
            
            MethodExpEntry mIndexer = info.Symbol;            
            
            if (mIndexer == null)
                ThrowError(SymbolError.NoAcceptableIndexer(location, alParamTypes, fIsLeft));
            
            Debug.Assert(info.MatchCount == 1, "Ambiguous indexers");
            Debug.Assert(!mIndexer.IsCtor); // indexer should not be a ctor
            
            return mIndexer;
        }


        // Helper to find an overloaded operator.
        // Return null if not found.
        public MethodExpEntry LookupOverloadedOperator(
            ISemanticResolver s,
            string stName,
            Type [] alParamTypes
            )
        {
            
            // Overloads just look in classes
            OverloadedErrorInfo info = new OverloadedErrorInfo();
            
            
            
            if (!IsInterface)
            {
                LookupMethodInClass(s, stName, alParamTypes, info);                
            }
            
            return info.Symbol;
        }
        


        // General all-purpose method lookup. Good for Class/Interface, overloaded, inherited, etc
        // This will delegate out to the proper helpers
        //
        // Find a method with the given stName that "matches" the given parameter list.
        // "matches" means that all arguments at the callsite can be implicitly converted
        // to the parameter type at the declaration
        //
        // Throw exception if method not found.
        public MethodExpEntry LookupMethod(
            ISemanticResolver s,             
            Identifier idName,
            Type [] alParamTypes,
            out bool fIsVarArg
            )
        {
            // Before we lookup anything, make sure we've resolved our scope
            this.EnsureResolved(s);
        
            fIsVarArg = false;
            
            string stName = idName.Text;
            FileRange location = idName.Location;
            //FileRange location = new FileRange();
            
            Debug.Assert(m_scope != null);
            Debug.Assert(alParamTypes != null);
            
            string stDecorated = GetDecoratedParams(stName, alParamTypes);
            
            OverloadedErrorInfo info = new OverloadedErrorInfo();
            
            MethodExpEntry sym = null;
            
            // If we're not an interface, then the method must exist in one of our base classes.
            // A normal lookup on scope searches base classes, so we're fine.
            if (!IsInterface)
            {
                LookupMethodInClass(s, stName, alParamTypes, info);
                
            } 
            else 
            {
                // Since classes just have a single base class, we have a simple linear search.
                // But since we can implement/inherit many interfaces, we have to search through
                // a tree here.
            
                // Do a quick broad seach for the method header. If that's not found, then we'll
                // never find the actual method / overload
                bool fHeader = LookForMethodHeaderInInterface(stName);
                if (!fHeader)
                    info.SetNoHeader();
                else 
                {                
                    // See if we have a direct match. Must look through entire tree for direct
                    // match first before searching for overload, else a shallow overload will
                    // hide an exact-match that's deeper in the tree.
                    LookupMethodInInterface(s, stDecorated, info);
                    if (info.MatchCount == 0)
                    {
                        // Only do search if we don't have a direct match
                        SearchForOverloadInInterface(s, stName, alParamTypes, info);

⌨️ 快捷键说明

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