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

📄 semanticchecker.cs

📁 charp compiler
💻 CS
📖 第 1 页 / 共 3 页
字号:
//-----------------------------------------------------------------------------
// File: SemanticChecker.cs
//
// Description:
//  Provide a class to traverse the AST and populate the symbol table.
//  
//-----------------------------------------------------------------------------

using System;
using System.Diagnostics;
using System.Reflection;
using System.Collections;
using System.Xml;

using Blue.Public;
using Log = Blue.Log;
using ErrorLog = Blue.Utilities.ErrorLog;

namespace SymbolEngine
{    
    //-----------------------------------------------------------------------------
    // Interface used by nodes during semantic resolution
    //-----------------------------------------------------------------------------
    
    /// <summary>
    /// Interface used by all functions doing symbol resolution. 
    /// </summary>
    /// <remarks>
    /// This interface provides context for symbols, scope lookup functions,
    /// type-utility functions, and safe exposure to an <see cref="ICLRtypeProvider"/>.
    /// It is not exposed to the driver.
    /// <para> The Driver starts symbol resolution via the <see cref="ISemanticChecker"/> interface.
    /// Resolution is done entirely in:
    /// <list type="number">
    /// <item>ResolveXX() methods on the <see cref="AST.Node"/> class </item>
    /// <item> Helper functions on the <see cref="SymEntry"/> classes. </item> 
    /// <item> The <see cref="SemanticChecker"/> class, which implements the ISemanticChecker. </item>
    /// </list>
    /// An ISemanticResolver interface exposes an API to allow these code sections 
    /// (and no other sections) to do symbol resolution.
    /// </para>    
    /// </remarks>
    public interface ISemanticResolver
    {
        //.....................................................................
        // Context
        //.....................................................................
        
        // Sets the current context that we lookup symbols against.
        // Returns the previous current context, which should be
        // passed to RestoreContext()
        Scope SetCurrentContext(Scope scopeNewContext);
        Scope GetCurrentContext();
        void RestoreContext(Scope scopePreviousContext);
        
        // Lookup a symbol in the current context.
        // The context includes the lexical scope stack, super scopes, 
        // and using directives
        SymEntry LookupSymbolWithContext(Identifier strName, bool fMustExist);
    
        // @todo - make this implicit in the Push & Pop scope    
        // Set the current class that we're processing
        void SetCurrentClass(TypeEntry type);
        TypeEntry GetCurrentClass();

        void SetCurrentMethod(MethodExpEntry m);
        MethodExpEntry GetCurrentMethod();
    
        //.....................................................................
        // Lookup.
        //.....................................................................
        
        // Lookup symbol in a particular scope (and its inherited scopes)    
        SymEntry LookupSymbol(Scope scope, Identifier id, bool fMustExist);
        SymEntry LookupSymbol(Scope scope, string st, bool fMustExist); // deprecated

        // Context-free
        // Lookup a system type, always must exist (else we throw internal error).
        TypeEntry LookupSystemType(string st);
            
        // Get the CLR type for an array / ref type. This will go through IProvider
        System.Type GetArrayType(ArrayTypeEntry sym);
        System.Type GetRefToType(System.Type t); // get a reference type

        // Lookup symbol in current scope stack
    
        // For importing, need a mapping from CLR types to blue types    
        TypeEntry ResolveCLRTypeToBlueType(System.Type t);    
        void AddClrResolvedType(TypeEntry sym);

        //.....................................................................
        // Utility
        //.....................................................................
        
        // For type checking, make sure that tDerived is of type tBase.
        // Throw an exception elsewise        
        void EnsureAssignable(AST.Exp expFrom, System.Type tTo);
        void EnsureAssignable(System.Type tFrom, System.Type cTo, FileRange location);
    
        // Ensure that a symbol is what we expect it to be (ie, we don't try to use a function name 
        // as a label);
        // If match, returns the symbol passed in (for nesting purposes)
        // Else throws an exception
        SymEntry EnsureSymbolType(SymEntry sym, System.Type tExpected, FileRange location);

        // Just checks, doesn't throw an exception either way    
        bool IsDerivedType(TypeEntry tBase, TypeEntry tDerived);
            
        //.....................................................................
        // Debugging
        //.....................................................................
        void Dump();
    }	

    

//-----------------------------------------------------------------------------
// Class to provide a context for semantic checking (symbol resolution)
//-----------------------------------------------------------------------------

/// <summary>
/// This class walks the AST to resolve all symbols.
/// </summary>
public class SemanticChecker : ISemanticChecker, ISemanticResolver
{
#region Checks
    // Dump the entire symbol contents to an XML file
    public void DumpSymbolTable(XmlWriter o)
    {
        o.WriteStartDocument();
            
        o.WriteStartElement("SymbolTable");
        if (m_scopeGlobal != null)            
            m_scopeGlobal.Dump(o, true);
                        
        o.WriteEndElement(); // SymbolTable
                                    
        o.WriteEndDocument();
            
        o.Close();
        
    }
#endregion
    
#region Error Handling

//-----------------------------------------------------------------------------
// Error handling
//-----------------------------------------------------------------------------    
    
    // Shortcut helper functions.
    public void PrintError(SymbolError.SymbolErrorException e)
    {    
        Blue.Driver.StdErrorLog.PrintError(e);
    }
    public void ThrowError(SymbolError.SymbolErrorException e)
    {    
        Blue.Driver.StdErrorLog.ThrowError(e);
    }
    
    
    
    
    
    public virtual void EnsureAssignable(
        AST.Exp expFrom, 
        System.Type tTo
    )
    {
        
        EnsureAssignable(expFrom.CLRType, tTo, expFrom.Location);
    }
#endregion

#region Type Checking functions    
    public virtual void EnsureAssignable(
        System.Type tFrom, 
        System.Type tTo, 
        FileRange location
    )
    {
        bool fOk = TypeEntry.IsAssignable(tFrom, tTo);
        if (!fOk)
        {
            ThrowError(SymbolError.TypeMismatch(tFrom, tTo, location));        
        }
    }
        
    
    // Just check. This is useful because sometimes we want to fail if something
    // is a derived type (ex, CatchHandlers shouldn't be derived type of a previous handler)
    public bool IsDerivedType(TypeEntry tBase, TypeEntry tDerived)
    {
    
        // Note that System.Array is a derived type for all arrays, so special case that
        if (tBase.CLRType == typeof(System.Array))
        {
            if (tDerived.IsArray)
                return true;
        }
        
        // @todo - For now, figure out how to safely convert System.Array to an array
        if (tDerived.CLRType == typeof(System.Array))
        {
            if (tBase.CLRType == typeof(System.Array))
                return true;
        }
        
    
        // Note that arrays may be different instances
        // but non arrays have only one TypeEntry per type
        // So peel off the arrays and get to the base type
        while (tBase.IsArray)
        {
            if (!tDerived.IsArray)
                return false;
                
            tBase = tBase.AsArrayType.ElemType;
            tDerived = tDerived.AsArrayType.ElemType;        
        }
        
        // Compare innermost types
        if (tDerived.IsArray)
        {
            return false;
        } 
        
        // Now walk up tDerived's chain looking for tBase
        TypeEntry t = tDerived;
        do
        {
            if (tBase == t)
                return true;
                
            t = t.Super;
        
        } while(t != null);
                   
        // Ok. So tBase is not a base class of tDerived. Check if tBase is an interface
        // that tDerive implements
        if (tBase.IsInterface)
        {
            if (IsBaseInterface(tBase, tDerived))
                return true;
        }
                       
        return false;        
    }

    // Helper to check if tDerived implements the interface tBaseInterface.
    protected bool IsBaseInterface(TypeEntry tBaseInterface, TypeEntry tDerived)
    {
        Debug.Assert(tBaseInterface.IsInterface);
        
        if (tBaseInterface == tDerived)
            return true;
        
        // Check superclasses
        if (tDerived.Super != null)
            if (IsBaseInterface(tBaseInterface, tDerived.Super))
                return true;

        // Check base interfaces
        foreach(TypeEntry ti in tDerived.BaseInterfaces)
        {
            if (IsBaseInterface(tBaseInterface, ti))
                return true;
        }
        
        return false;
    }

    
    public SymEntry EnsureSymbolType(SymEntry sym, System.Type tExpected, FileRange location)
    {
        if (sym == null)
            return null;
/*
        Type tSym = sym.GetType();
        if (tSym == tExpected)
            return sym;

        if (tSym.IsSubclassOf(tExpected))
            return sym;
*/
        bool fMatch = SymbolEngine.TypeEntry.IsAssignable(sym.GetType(), tExpected);
        if (fMatch)
            return sym;

        ThrowError(SymbolError.BadSymbolType(sym, tExpected, location));
/*
        this.ThrowError(Code.cBadSymbolType,
            location,
            "Symbol '" + sym.Name + "' must be of type '" + tExpected.ToString() + "', not '" +
            sym.GetType().ToString() + "'");
*/
        return sym;
    }
#endregion 
    
//-----------------------------------------------------------------------------           
// Add aliases for the default types      
// Must have loaded mscorlib.dll first
//-----------------------------------------------------------------------------
    protected void AddDefaultTypes(Scope scopeGlobal)
    {               
    // Alias        
        scopeGlobal.AddAliasSymbol("int", LookupSystemType("Int32"));        
        scopeGlobal.AddAliasSymbol("void", LookupSystemType("Void"));
        scopeGlobal.AddAliasSymbol("char", LookupSystemType("Char"));
        scopeGlobal.AddAliasSymbol("bool", LookupSystemType("Boolean"));
        scopeGlobal.AddAliasSymbol("string", LookupSystemType("String"));    
        scopeGlobal.AddAliasSymbol("object", LookupSystemType("Object"));
        
    // Ensure that compound types that are backed by a core clr type are resovled.
    // (mainly Array, Enum, Delegate)
        TypeEntry tArray = LookupSystemType("Array");
        tArray.EnsureResolved(this);

        TypeEntry tEnum = LookupSystemType("Enum");
        tEnum.EnsureResolved(this);
        
        TypeEntry tDelegate = LookupSystemType("MulticastDelegate");
        tDelegate.EnsureResolved(this);
        
    }

#region Importing Assemblies     
//-----------------------------------------------------------------------------
// Create the scopes for an imported types
//-----------------------------------------------------------------------------
    Scope CreateImportedContext(System.Type tImport)
    {
        // Traverse namespaces to find scope
        Scope scope = m_scopeGlobal;
        string s = tImport.ToString();
               
        // In a type's string name, the '.' separates namespaces,
        // the '+' separates for nested classes.        
        // Valid form:
        // i.i.i+i+i+i
                        
        int iStart  = 0;

⌨️ 快捷键说明

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