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

📄 objexpast.cs

📁 charp compiler
💻 CS
📖 第 1 页 / 共 5 页
字号:
        

        // Now we're back to normal...
        
                                
        // Figure out what constructor we're calling    
        if (m_tType.BlueType.IsStruct && (alParamTypes.Length == 0))
        {
            // Structs have no default constructor
            
        } else {    
            // Else resolve the ctor
            bool fIsVarArg;
            m_symCtor = m_tType.BlueType.LookupMethod(
                s, 
                new Identifier(m_tType.BlueType.Name, this.Location), 
                alParamTypes, 
                out fIsVarArg);
        }
        
        //(m_tType.TypeRec, s);    
        CalcCLRType(s);
        
        return this;
    }
    
    protected override Type CalcCLRTypeHelper(ISemanticResolver s)
    {
        return m_tType.BlueType.CLRType;
    }
#endregion    
}

//-----------------------------------------------------------------------------
// New array
// Expression List - specifies size of array, eval at runtime
// Initilizer List - specifies intializer list
//-----------------------------------------------------------------------------
public class NewArrayObjExp : Exp
{
    // Implicit size from init list
    public NewArrayObjExp(
        ArrayTypeSig tArrayType,    // includes rank specifiers
        ArrayInitializer aInit      // mandatory
    )
    {
        Debug.Assert(tArrayType != null);
        Debug.Assert(aInit != null);
        
        m_tFullType = tArrayType;
        this.m_arExpList = null;
        this.m_ArrayInit = aInit;

        // @todo - this is wrong
        m_filerange = tArrayType.Location;    
    }
    
    public NewArrayObjExp(
        ArrayTypeSig tArrayType,    // full array type (includes rank)
        Exp [] arExpSize,           // rank to allocate, eval at runtime
        ArrayInitializer aInit      // optional initilizer list        
    )
    {
        Debug.Assert(tArrayType != null);
        Debug.Assert(arExpSize != null);
        
        m_tFullType = tArrayType;
        this.m_arExpList = arExpSize;
        this.m_ArrayInit = aInit;
        
        // @todo - this is wrong
        m_filerange = tArrayType.Location;
    }        
    
    
  
#region Checks
    //-----------------------------------------------------------------------------
    // Debugging check
    //-----------------------------------------------------------------------------
    public override void DebugCheck(ISemanticResolver s)
    {        
        Debug.Assert(this.CLRType.IsArray);
        //Debug.Assert(TypeRec.AsArrayType.ElemType == ElemType.TypeRec);
        
        if (HasInitializerList) {
            ArrayInit.DebugCheck(s);
        }

        if (DimensionExpList != null)
        {
            foreach(Exp e in DimensionExpList)
            {
                e.DebugCheck(s);
            }
        }
    }
    
    // Dump as XML
    public override void Dump(XmlWriter o)
    {    
        o.WriteStartElement("NewArrayObjExp");
        o.WriteAttributeString("elementtype", ElemType.ToString());
        

        if (HasInitializerList)
        {
            ArrayInit.Dump(o);
        }
            
        o.WriteEndElement();
        
    } 
    
    public override void ToSource(System.CodeDom.Compiler.IndentedTextWriter sb)    
    {
        sb.Write("new {0}[{1}]", this.ElemType.ToString(), this.DimensionExpList.Length);
    }
#endregion    

#region Properties & Data    
    // The array type that this expression will evaluate to
    protected ArrayTypeSig m_tFullType; 
    
    // The type of object that we're allocating
    public TypeEntry ElemType
    {
        get { return m_tFullType.ElemType; }
    }

    // Array Initializer
    ArrayInitializer m_ArrayInit;
    public ArrayInitializer ArrayInit
    {
        get { return m_ArrayInit; }
    }
/*    
    // A block statement that has the code needed to 
    // initialize the array for the Initializer list
    BlockStatement m_stmtInit;
    public BlockStatement InitStmt
    {
        get { return m_stmtInit; }
    }
  */  
    // Return true if we have an init list, else false
    public bool HasInitializerList
    {
        get { return m_ArrayInit != null; }
    }

    // Expression list for the size to allocate
    protected Exp[] m_arExpList;
    public Exp[] DimensionExpList
    {
        get { return m_arExpList; }
    }
    
    ArrayTypeEntry m_symbol;
    public ArrayTypeEntry ArraySymbol    
    {
        get { return m_symbol; }
    }
    
#endregion
                
    // Do codegen
    public override void GenerateAsRight(CodeGen.EmitCodeGen gen)
    {        
        gen.Generate(this);
    }

#region Resolution
    // Resolve
    protected override Exp ResolveExpAsRight(ISemanticResolver s)
    {
        if (m_symbol != null)
            return this;
            
        // Resolve the type we're allocating        
        m_tFullType.ResolveType(s);
        Debug.Assert(this.ElemType != null);
        
        // Resolve the initializer list        
        if (HasInitializerList) 
        {
            // If we specified a length, it'd better match the intializer list length.
            if (DimensionExpList != null)
            {
                Debug.Assert(this.DimensionExpList.Length == 1, "@todo -multidimensional arrays");
                Exp e = DimensionExpList[0];
                // e must be a compile time constant who's value matches the ArrayInit length
                IntExp eInt = e as IntExp;
                
                if (eInt == null)
                    ThrowError(SymbolError.MustBeCompileTimeConstant(e));
                
                if (eInt.Value != m_ArrayInit.Length)
                    ThrowError(SymbolError.NewArrayBoundsMismatch(this));
            }
        
            m_ArrayInit.Resolve(s, this.ElemType);
            
            // The ability to not specifiy a dimension list is just syntactic sugar.
            // So if we still don't have it, we'd better fill it in based of the array-init list.
            if (DimensionExpList == null)
            {
                m_arExpList = new Exp[] { new IntExp(m_ArrayInit.Length, this.Location) };                
            }        
        }
        
        Debug.Assert(DimensionExpList != null);                
        for(int i = 0; i < this.m_arExpList.Length; i++)
        {
            ResolveExpAsRight(ref m_arExpList[i], s);
        }
        

        m_symbol = new ArrayTypeEntry(m_tFullType, s);
        CalcCLRType(s);
                
        // Transform an initializer list into an CompoundExpression:
        // new T[] { e0, e1, ... en} 
        // <DeclareTemp(x), x = new T[], x[0]=e0, ... x[n]=en, x>
        if (HasInitializerList)
        {
            DeclareLocalStmtExp declare_x = new DeclareLocalStmtExp(this.ArraySymbol); 
                
            LocalExp x = declare_x.GetLocal();
            
            StatementExp [] list = new StatementExp[m_ArrayInit.Length + 2];
            list[0] = declare_x;
            list[1] = new AssignStmtExp(x, this);
            for(int i = 0; i < m_ArrayInit.Length; i++)
                list[i + 2] = new AssignStmtExp(
                    new ArrayAccessExp(
                        x,
                        new IntExp(i, null)
                    ),
                    m_ArrayInit.GetExpAt(i)
                );
            
            // Strip the ArrayInitializer off this node.    
            m_ArrayInit = null;
                            
            StatementExp c = new CompoundStmtExp(list, x);
            
            StatementExp.ResolveExpAsRight(ref c, s);
            
            return c;
        } // end has Initializer
                
        return this;
    }
        
    protected override Type CalcCLRTypeHelper(ISemanticResolver s)
    {
        return m_symbol.CLRType;
    }
#endregion    
}
#endregion // New

//-----------------------------------------------------------------------------
// Array access
// May be an actual array access, or an indexer overload
// If this is an indexer, we expect to be transformed into methodcalls
// before we get to codegen
//-----------------------------------------------------------------------------
public class ArrayAccessExp : Exp
{
    public ArrayAccessExp(
        Exp expLeft,
        Exp expIndex
        )
    {
        Debug.Assert(expLeft != null);
        Debug.Assert(expIndex != null);
    
        m_oeLeft = expLeft;
        m_expIndex = expIndex;
    
        // @todo- this is wrong
        m_filerange = m_oeLeft.Location;                
    }

#region Checks
    //-----------------------------------------------------------------------------
    // Debugging check
    //-----------------------------------------------------------------------------
    public override void DebugCheck(ISemanticResolver s)
    {
        m_oeLeft.DebugCheck(s);
        m_expIndex.DebugCheck(s);
    }
    
    // Dump as XML
    public override void Dump(XmlWriter o)
    {
        o.WriteStartElement("ArrayAccessExp");
        m_oeLeft.Dump(o);
        m_expIndex.Dump(o);                    
        o.WriteEndElement();
    } 
    
#endregion

#region Properties & Data
    // Array object on the left side to be dereferenced
    protected Exp m_oeLeft;
    public Exp Left
    {
        get { return m_oeLeft; }
    }
    
    // Expression to evaluate to integer index
    protected Exp m_expIndex;
    public Exp ExpIndex
    {
        get { return m_expIndex; }
    }
    
    // Is this ArrayAccess actually an indexer?
    bool m_fIsIndexer;
    public bool IsIndexer
    {
        get  {return m_fIsIndexer; }
    }
    
    // Get the element type as a CLR type
    // If we're an indexer, this will be the return type on the property
    public System.Type CLRElemType
    {            
        get { 
            // ...
            // ...
            // There is a bug in .NET where references are not properly stripped, so
            // we have to be a little more round-about here.
            System.Type tLeft = Left.CLRType;
            string stLeft = tLeft.ToString();
            
            System.Type tNoRef;
            if (tLeft.IsByRef) 
                tNoRef = tLeft.GetElementType();
            else
                tNoRef = tLeft;
                
            string stNoRef = tNoRef.ToString();                
                
            Debug.Assert(!tNoRef.IsByRef);                
            Debug.Assert(tNoRef.IsArray);
            
            System.Type tElem = tNoRef.GetElementType();
            string stElem = tElem.ToString();

            Debug.Assert(!tElem.IsByRef); // Can't be a ref, could still be an array.
            return  tElem;
        }
    }
#endregion       

#region Generate        
    // Do codegen
    public override void GenerateAsRight(CodeGen.EmitCodeGen gen)
    {   
        Debug.Assert(!IsIndexer, "Don't codegen Indexers as Array Access");
        gen.Generate(this);
    }
    
    public override void GenerateAsLeftPre(CodeGen.EmitCodeGen gen)
    {        
        Debug.Assert(!IsIndexer, "Don't codegen Indexers as Array Access");
        gen.GenerateAsLeftPre(this);
    }
    
    public override void GenerateAsLeftPost(CodeGen.EmitCodeGen gen)
    {   
        Debug.Assert(!IsIndexer, "Don't codegen Indexers as Array Access");     
        gen.GenerateAsLeftPost(this);
    }
    
    public override void GenerateAddrOf(CodeGen.EmitCodeGen gen)
    {
        Debug.Assert(!IsIndexer, "Don't codegen Indexers as Array Access");
        gen.GenerateAddrOf(this);
    }
#endregion

#region Resolve
    protected override Exp ResolveExpAsLeft(ISemanticResolver s)
    {
        return ResolveInternal(s, true);
    }
    
    // Resolve
    protected override Exp ResolveExpAsRight(ISemanticResolver s)
    {
        return ResolveInternal(s, false);
    }
    
    // Internal helper. Since the left & right cases are close enough
    // we want to merge them into a function.
    private Exp ResolveInternal(ISemanticResolver s, bool fIsLeft)
    {
        ResolveExpAsRight(ref m_oeLeft, s);
        ResolveExpAsRight(ref m_expIndex, s);
        
    // @todo - check that m_expIndex is an integer
    
    // Check for indexers:
    // If the Left is not an array, then we must be an indexer.
    // Strip references, So T[]& --> T[]
        System.Type t = m_oeLeft.CLRType;
        if (t.IsByRef)
            t = t.GetElementType();
            
        if (!t.IsArray)
        {            
            m_fIsIndexer = true;
            
            
            // If we're the leftside, we have a problem. We don't know the exp on the RS,
            // so we don't have a full signature, so we don't know what we're supposed to
            // change too. So just leave it that we're an indexer and let our parent
            // in the AST resolve us.
            // But this also means that we don't have a good thing to set our CLR type too.
            // So we just don't call CalcCLRType(). That's ok since our parent will drop
            // this node immediately anyways.
            if (fIsLeft)
            {
                return this;
            }
            
            // Rightside: get_Item(idx);
            System.Type [] alParams = new Type [] {
                this.ExpIndex.CLRType
 

⌨️ 快捷键说明

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