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

📄 expast.cs

📁 charp compiler
💻 CS
📖 第 1 页 / 共 5 页
字号:
//-----------------------------------------------------------------------------
// File: ExpAST.cs
//
// Description: All Expression nodes in the AST
// See AST.cs for details
//-----------------------------------------------------------------------------

using System;
using System.Diagnostics;
using System.Xml;

using SymbolEngine;
using Blue.Public;
using CodeGen = Blue.CodeGen;


namespace AST
{
#region Exp base class
//-----------------------------------------------------------------------------        
// General expression
//-----------------------------------------------------------------------------    

/// <summary>
/// Abstract base class for all expressions.
/// </summary>
/// <remarks>
/// <para>Provides virtual functions for Resolving as a left or right hand side expressions.
/// All expressions have an associated System.Type (the <see cref="Exp.CLRType"/> property).</para>
/// <para>When an expression is resolved, it can mutate itself into a new expression.The 
/// <see cref="Exp.ResolveExpAsLeft"/> and <see cref="Exp.ResolveExpAsRight"/> instance members
/// return a exp. If the expression was not mutated, they return the 'this' pointer. If a mutation
/// does occur, they could return a totally new, resolved, exp node. This is useful for code
/// transforms. (ex: constant-folding).</para>
/// </remarks>
public abstract class Exp : Node
{
    //.........................................................................
    // Semantic resolution. Resolve the exp as either a LHS or RHS value.
    //.........................................................................
    
    // Resolve the expression as a LHS value
    public static void ResolveExpAsLeft(ref Exp e, ISemanticResolver s)
    {
        e = e.ResolveExpAsLeft(s);
        Debug.Assert(e != null);
    }
    
    protected virtual Exp ResolveExpAsLeft(ISemanticResolver s)
    {
        // Default impl - most expressions aren't valid on the LHS.
        //s.ThrowError_NotValidLHS(this.Location);
        ThrowError(SymbolError.NotValidLHS(this.Location));
        return null;
    }
   
    // Resolve expression as a RHS value. The exp node can totally change on us
    // (operator overloading, constant folding, etc), so we must pass as a ref
    public static void ResolveExpAsRight(ref Exp e, ISemanticResolver s)
    {
        // Debugging helper. Useful when we want to break when resolving 
        // a particular symbol.
        
        #if false   
             
        // Set lTarget to a symbol that we want to see resolved.
        FileRange lTarget = new FileRange("SemanticChecker.cs", 143, 39, 143, 43);
        if (lTarget.Equals(e.Location))
        {
            System.Diagnostics.Debugger.Break();
        }
        
        #endif
        e = e.ResolveExpAsRight(s);
        Debug.Assert(e != null);
    }
   
    // Helper to resolve the expression as RHS value.
    // Return the newly-resolved exp node. In most cases, that will just be
    // the old node, but in a resolved state. For things like operator overloading,
    // it will be a totally different node.
    // Note that we must expose this version because 'ref Exp' is not assignable
    // with any derived expression.
    protected abstract Exp ResolveExpAsRight(ISemanticResolver s);    

    //.........................................................................
    // Code generation
    // To codegen something like: 'a=b', we need to be able to do:
    // [a]lhs_pre   // emit code to load context for the assignment
    // [b]rhs       // emit code to load value to be assigned
    // [a]lhs_post  // emit code to actually store the results
    //
    // Most expressions will only need a rhs.
    //.........................................................................
        
    public virtual void GenerateAsLeftPre(CodeGen.EmitCodeGen gen)
    {
        Debug.Assert(false, "Didn't implement GenerateAsLeftPre");
    }    
    public virtual void GenerateAsRight(CodeGen.EmitCodeGen gen)
    {
        Debug.Assert(false, "Didn't implement GenerateAsRight");
    }
    public virtual void GenerateAsLeftPost(CodeGen.EmitCodeGen gen)
    {
        Debug.Assert(false, "Didn't implement GenerateAsLeftPost");
    }
    
    
    //.........................................................................
    // Code Generation - Generate the address of this expression    
    //.........................................................................
    public virtual void GenerateAddrOf(CodeGen.EmitCodeGen gen)
    {
        // Can't get the addr of most expressions
        //Debug.Assert(false, "Didn't implemented GenerateAddrOf");
        // Default impl, evaluate as RHS, store in temp, gen addr of that.
        gen.GenerateAddrOf(this);
    }
    
    // @todo - not really working yet. We don't do constant folding.
    //.........................................................................
    // Simplifying an expression that we pass in. Pass out the simplified
    // expression (or the same thing we passed in if we can't simplify)
    //.........................................................................
    public static void TrySimplify(ref Exp e)
    {
        e = e.TrySimplify();
    }

    // @todo - not really working yet.
    // Actual workhorse,  Default behavior, can't simplify, so return the original
    protected virtual Exp TrySimplify()
    {
        return this;
    }
    
    // Return true iff the given expression is allowed to have a null type
    public static bool CanBeNullType(Exp e)
    {
        return (e is NullExp) || (e is IfExp) || (e is ArgExp) || (e is NamespaceExp);
    }
    
    // Determine the CLR Type of this expression
    // As a convenience, return the clr type to saves us from having to 
    // call CLRType
    public System.Type CalcCLRType(ISemanticResolver s)
    {
        Type tOld = m_clrType;
        m_clrType = CalcCLRTypeHelper(s);   
        Debug.Assert(m_clrType != null || Exp.CanBeNullType(this));
     
        // Assert that if we called this multiple times, the value hasn't changed on us
        Debug.Assert(((tOld == null)) || (tOld == m_clrType));

        // @todo - we don't resolve pointers yet....
        // The only place we can use them is in evaluating a MethodPtr for a delegate ctor.
        if (m_clrType == Type.GetType("System.IntPtr"))
        {
            Debug.Assert(this is MethodPtrExp);
            return m_clrType;
        }


        // @todo - move this into a place w/ better perf...
        // EnsureResolved
        if (m_clrType != null)
        {
            TypeEntry t = s.ResolveCLRTypeToBlueType(m_clrType);
            t.EnsureResolved(s);
        }

        return m_clrType;
    }

    // This gets called by CalcCLRType()
    // Derived classes override this and return the clr type    
    protected virtual Type CalcCLRTypeHelper(ISemanticResolver s)
    {
        // This should be implemented
        Debug.Assert(false, "@todo - impl");
        return null;
    }
    
    public System.Type CLRType
    {
        get { return m_clrType; }
    }

    private System.Type m_clrType;
}
#endregion


//-----------------------------------------------------------------------------        
// Expression to represent an argument to a method call
//-----------------------------------------------------------------------------        

/// <summary>
/// Node for an argument in a method call
/// </summary>
/// <remarks>
/// An ArgExp represents each argument in a <see cref="MethodCallExp"/>.
/// <para><children>Children:<list type="bullet">
/// <item><see cref="EArgFlow"/> - specify if this is an 'in', 'out', or 'ref' parameter.</item>
/// <item><see cref="Exp"/> - specify the expression for this parameter</item>
/// </list></children></para>
/// </remarks>
public class ArgExp : Exp
{
    public ArgExp(AST.EArgFlow eFlow, Exp exp)
    {
        Debug.Assert(exp != null);        
        Debug.Assert(!(exp is ArgExp), "ArgExp should never wrap an ArgExp");
        m_exp = exp;
        m_eFlow = eFlow;
    }

#region Checks
    public override void DebugCheck(ISemanticResolver s)
    {
        m_exp.DebugCheck(s);
    }

    // Dump as XML
    public override void Dump(XmlWriter o)
    {
        o.WriteStartElement("ArgExp");
        o.WriteAttributeString("flow", m_eFlow.ToString());
        m_exp.Dump(o);
        o.WriteEndElement();
    }
    
    public override void ToSource(System.CodeDom.Compiler.IndentedTextWriter sb)    
    {
        sb.Write("<{0}>", this.m_eFlow.ToString());
        this.m_exp.ToSource(sb);
    }
#endregion    
    
#region Properties & Data
    EArgFlow m_eFlow;
    public EArgFlow Flow
    {
        get { return m_eFlow; }
    }
    
    Exp m_exp;
    public Exp InnerExp
    {
        get { return m_exp; }
    }
#endregion

#region Resolution
    protected override Type CalcCLRTypeHelper(ISemanticResolver s)
    {
        // Get the type of our inner
        Type t = m_exp.CalcCLRType(s);
        
        // If we've already got a reference, then we're ok.
        // Also ok if we're null (since literals can't be passed as a ref/out)
        if ((t == null) || (t.IsByRef))
            return t;
        
        // Ref & Out params are actually type 'T&', not 'T'
        if (Flow == EArgFlow.cRef || Flow == EArgFlow.cOut)
        {
            t = s.GetRefToType(t);        
        }
        
        return t;
    }

    // Resolve the expression as a LHS value
    protected override Exp ResolveExpAsLeft(ISemanticResolver s)
    {
        Debug.Assert(m_eFlow == EArgFlow.cOut | m_eFlow == EArgFlow.cRef);
        ResolveExpAsLeft(ref m_exp, s);
        CalcCLRType(s);
        return this;
    }
   
    // Resolve the expression as RHS value.
    protected override Exp ResolveExpAsRight(ISemanticResolver s)
    {
        //Debug.Assert(m_eFlow == EArgFlow.cIn | m_eFlow == EArgFlow.cRef);
        Exp.ResolveExpAsRight(ref m_exp, s);
        CalcCLRType(s);
        
        return this;
    }
#endregion

    public override void GenerateAsRight(CodeGen.EmitCodeGen gen)
    {
    /*
        if (Flow == EArgFlow.cIn)
            m_exp.GenerateAsRight(gen);
        else
            m_exp.GenerateAddrOf(gen);            
    */
        gen.GenerateArg(this);            
    }

}


//-----------------------------------------------------------------------------        
// Expression that represents a type
// Should only be used as an intermediate node.
//-----------------------------------------------------------------------------        
public class TempTypeExp : Exp
{
    public TempTypeExp(TypeSig t)
    {
        m_tSig = t;
    }

    TypeSig m_tSig;
    public TypeSig TypeSigRec
    {
        get { return m_tSig; }
    }

#region Checks
    public override void DebugCheck(ISemanticResolver s)
    {
        Debug.Assert(false);
    }

    // Dump as XML
    public override void Dump(XmlWriter o)
    {
        Debug.Assert(false);
    }

    public override void ToSource(System.CodeDom.Compiler.IndentedTextWriter sb)    
    {
        sb.Write("<T>{0}", this.m_tSig.ToString());
    }
#endregion

#region Resolution
    // Semantic resolution
    protected override Exp ResolveExpAsRight(ISemanticResolver s)
    {
        Debug.Assert(false);        
        return null;
    }    

    // Code generation
    public override void GenerateAsRight(CodeGen.EmitCodeGen gen)
    {
        Debug.Assert(false);
    }
    
    
    protected override Type CalcCLRTypeHelper(ISemanticResolver s)
    {        
        Debug.Assert(false);
        return null;
    }
#endregion
} // end TypeExp


#region Statement Expressions
/// <summary>
/// Abstract base class for expression that have sideeffects and can be used as statements.
/// </summary>
/// <remarks>
/// <para>Some expressions, like assignment, methodcalls, and the ++,-- operators
/// have sideeffects and so they can be used as a statement.</para>
/// <para>A StatementExp can be used directly as an expression, or it can be held in a 
/// <see cref="ExpStatement"/> to be used as a statement.</para>
/// </remarks>
public abstract class StatementExp : Exp
{   
    // Statement expressions can be generated as a statement or expression.
    // As an expression, they must leave a value on the top of the stack
    // As a statement, they don't leave a value on top (and hence may
    // be able to have a more efficient impl). 
    // Normal Generate() will generate as a RHS expression.    
    
    public virtual void GenerateAsStatement(CodeGen.EmitCodeGen gen)
    {        
    // Default impl generates as a RHS exp and just pops the value off    
        gen.GenerateAsStatement(this);
    }
    
    // Allow safe resolving on Statement Exp. Allowed to change to another StmtExp
    public static void ResolveExpAsRight(ref StatementExp se, ISemanticResolver s)
    {
        Exp e = se;
        Exp.ResolveExpAsRight(ref e, s);
        if (e is StatementExp)
            se = (StatementExp) e;
        else
            Debug.Assert(false, "Shouldn't have resolved to a non-stmtexp");            
            
        Debug.Assert(se != null);
    }
}

#if true
//-----------------------------------------------------------------------------
// Declares a temporary local var
// We must execute this as a statement to actually create the local,
// And then we can use the GetLocal() to get a LocalExp to refer to the temp.
//-----------------------------------------------------------------------------
public class DeclareLocalStmtExp : StatementExp
{
    public DeclareLocalStmtExp(System.Type t, ISemanticResolver s)
        : this(s.ResolveCLRTypeToBlueType(t))
    {           
    }
    
    public DeclareLocalStmtExp(TypeEntry t)    
    {
        LocalVarExpEntry l = new LocalVarExpEntry();
        l.m_strName = ".temp_local_" + m_count;
        m_count++;
        l.m_type = t;
        
        m_exp = new LocalExp(l);
    }

#region Properties & Data
    LocalExp m_exp;
    public LocalExp GetLocal()
    {
        return m_exp;
    }

⌨️ 快捷键说明

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