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

📄 expast.cs

📁 charp compiler
💻 CS
📖 第 1 页 / 共 5 页
字号:
    protected override Type CalcCLRTypeHelper(ISemanticResolver s)
    {        
        return typeof(bool);
    }
#endregion
    
    // Code generation
    public override void GenerateAsRight(CodeGen.EmitCodeGen gen)
    {
        gen.Generate(this);
    }


}

//-----------------------------------------------------------------------------    
// Binary operations
//-----------------------------------------------------------------------------        
public class BinaryExp : Exp
{
    // @dogfood - 'new String[]' not needed when we have an array of literals,
    private static string [] m_ops = new String[] {
        "+", "-", "*", "/", "%",
        "&&", "||",
        "==", "!=", "<", ">", "<=", ">=",
        "&", "|", "^",
        "<<", ">>"
    };
    
    public static string OpName(BinaryOp op)
    {
        return m_ops[(int) op];
    }
                    
    public enum BinaryOp
    {
        cAdd,
        cSub,
        cMul,
        cDiv,
        cMod,
        
        cAnd,
        cOr,
                
        cEqu,
        cNeq,
        cLT,
        cGT,
        cLE,
        cGE,
        
        cBitwiseAnd,
        cBitwiseOr,
        cBitwiseXor,
        
        cShiftLeft,
        cShiftRight,
        
        cInvalid,
    }
    
    public BinaryExp(Exp left, Exp right, BinaryOp op)
    {
        Debug.Assert(left != null);
        Debug.Assert(right != null);
        
        //m_filerange = FileRange.Merge(left.Location, right.Location);
        
        m_left = left;
        m_right = right;
        m_op = op;
    }

#region Properties & Data    
    protected Exp m_left;
    protected Exp m_right;
    protected BinaryOp m_op;

    public Exp Left
    {
        get { return m_left; }
    }            
    
    public Exp Right
    {
        get { return m_right; }
    }
    
    public BinaryOp Op
    {
        get { return m_op; }
    }
#endregion

#region Resolution
    // Try and simplify
    protected override Exp TrySimplify()
    {
        TrySimplify(ref m_left);
        TrySimplify(ref m_right);

        IntExp i1 = Left as IntExp;
        IntExp i2 = Right as IntExp;
        if (i1 != null && i2 != null)
        {
            int n1 = i1.Value;
            int n2 = i2.Value;
            switch(Op)
            {
                case BinaryOp.cAdd:
                    return new IntExp(n1 + n2, Location);
            }
        }

        // Can't simplify
        return this;
    }

        
    // Nothing to resolve for literal expressions
    protected override Exp ResolveExpAsRight(ISemanticResolver s)
    {   
        // Always resolve our children     
        ResolveExpAsRight(ref m_left, s);
        ResolveExpAsRight(ref m_right, s);
        
        // If we don't match a predefined operator, then check for overloads
        if (!MatchesPredefinedOp(Op, this.Left.CLRType, this.Right.CLRType))
        {
            // Packagage Left & Right into parameters for a method call
            ArgExp [] args = new ArgExp [2] {
                new ArgExp(EArgFlow.cIn, m_left),
                new ArgExp(EArgFlow.cIn, m_right)
            };
                                    
            // Check for delegate combination
            // D operator+(D, D)
            // D operator-(D, D)            
            if (AST.DelegateDecl.IsDelegate(m_left.CLRType))
            {
                if (m_left.CLRType == m_right.CLRType)
                {
                    if (Op == BinaryOp.cAdd || Op == BinaryOp.cSub)
                    {
                        System.Type d = m_left.CLRType;
                        
                        // Translates to:
                        // op+ --> (D) System.Delegate.Combine(left, right)
                        // op- --> (D) System.Delegate.Remove(left, right)
                        
                        TypeEntry tDelegate = s.LookupSystemType("MulticastDelegate");
                        string stName = (Op == BinaryOp.cAdd) ? "Combine" : "Remove";
                        
                        bool dummy;
                        MethodExpEntry sym = tDelegate.LookupMethod(s, new Identifier(stName), 
                            new Type[] { d, d}, out dummy);
                        
                        
                        Exp call2 = new CastObjExp(
                            new ResolvedTypeSig(d, s),
                            new MethodCallExp(
                                null,sym, args, s)
                        );
                        
                        Exp.ResolveExpAsRight(ref call2, s);
                        return call2;                                
                    
                    }
                }
            
            } // end delgate op+ check
                                            
            // Check for System.String.Concat().
            // @todo - this should be able to compress an entire subtree, not just 2 args.
            // (ie, a+b+c -> String.Concat(a,b,c);
            // So we can't merge this into the SearchForOverload.
            // But for now we'll be lazy...
            if ((Op == BinaryOp.cAdd) && (Left.CLRType == typeof(string) || Right.CLRType == typeof(string)))
            {                
                Exp call2 = new MethodCallExp(                    
                        new DotObjExp(
                            new SimpleObjExp(
                                new Identifier("System", this.m_filerange)
                            ),
                            new Identifier("String", this.m_filerange)),
                        new Identifier("Concat", m_filerange),
                        args);
                call2.SetLocation(this.Location);
                Exp.ResolveExpAsRight(ref call2, s);
                        
                return call2;
            }
        
            MethodExpEntry  m = SearchForOverloadedOp(s);
            if (m == null && (Op == BinaryOp.cEqu || Op == BinaryOp.cNeq))
            {
                // If it's '==' or '!=', then it's ok if we didn't find 
                // an overload.
            } else 
            {
                // Couldn't find an overload, throw error
                if (m == null)
                {
                    //ThrowError_NoAcceptableOperator(s, this.Location, m_left.CLRType, m_right.CLRType, Op);
                    ThrowError(SymbolError.NoAcceptableOperator(this.Location, m_left.CLRType, m_right.CLRType, Op));
                }
                
                // Replace this node w/ the method call            
                MethodCallExp call = new MethodCallExp(null, m, args, s);
                call.SetLocation(this.Location);
                
                return call;
            }
        }
        
        
        CalcCLRType(s);
        
        return this;
    }
    
    // Search for an overloaded operator. Return the symbol for the method if found.
    // Return null if not found.
    MethodExpEntry SearchForOverloadedOp(ISemanticResolver s)
    {
        Type [] alParams = new Type[2];
        alParams[0] = m_left.CLRType;
        alParams[1] = m_right.CLRType;
        
        
        
        string stName = MethodDecl.GetOpOverloadedName(this.Op);
        
        MethodExpEntry sym;
        
        if (m_left.CLRType != null)
        {
            TypeEntry t1 = s.ResolveCLRTypeToBlueType(m_left.CLRType);
            sym = t1.LookupOverloadedOperator(s, stName, alParams);
            if (sym != null)
                return sym;
        }
        
        if (m_right.CLRType != null)
        {
            TypeEntry t2 = s.ResolveCLRTypeToBlueType(m_right.CLRType);
            sym = t2.LookupOverloadedOperator(s, stName, alParams);
            if (sym != null)
                return sym;
        }
                
        return null; 
    }
    
    
    // Helpers for detecting if we match predefined ops
    // Return true if we're any integral type, else false.
    static public bool IsNumber(System.Type t)
    {
        return t == typeof(int) || t == typeof(char);
    }
    static public bool IsBool(System.Type t)
    {
        return t == typeof(bool);
    }
    static public bool IsInteger(System.Type t)
    {
        return t == typeof(int) || t == typeof(char);
    }
    static public bool IsEnum(System.Type t)
    {
        return (t != null) && t.IsEnum;
    }
        
    // Return true if our param types let us match a predefined operator.
    // Else return false (which implies that we must match against an 
    // overloaded operator)
    // @todo - combine w/ CalcCLRTypeHelper()
    static public bool MatchesPredefinedOp(BinaryOp op, Type clrLeft, Type clrRight)
    {
        // For arithmetic ops, only predefined if both args are numbers
        if (op == BinaryOp.cAdd || op == BinaryOp.cMul || op == BinaryOp.cSub || 
            op == BinaryOp.cDiv || op == BinaryOp.cMod ||
            op == BinaryOp.cShiftLeft || op == BinaryOp.cShiftRight)
        {
            return IsNumber(clrLeft) && IsNumber(clrRight);                
        }
        
        if (op == BinaryOp.cEqu || op == BinaryOp.cNeq)
        {
            if (IsNumber(clrLeft) && IsNumber(clrRight)) 
                return true;
            if (IsBool(clrLeft) && IsBool(clrRight))
                return true;
            if (IsEnum(clrLeft) && IsEnum(clrRight))
                return true;                
            return false;                
        }
        
        // Bitwise operators work on either bool or integers
        if (op == BinaryOp.cBitwiseAnd || op == BinaryOp.cBitwiseOr || op == BinaryOp.cBitwiseXor)
        {
            if (IsInteger(clrLeft) && IsInteger(clrRight)) 
                return true;
            if (IsBool(clrLeft) && IsBool(clrRight))
                return true;
            if (IsEnum(clrLeft) && IsEnum(clrRight)) // @todo -only if flags attribute specified
                return true;                
            return false;  
        }
                
        // Relational ops only work on ints
        if (op == BinaryOp.cLT || op == BinaryOp.cGT ||
            op == BinaryOp.cLE || op == BinaryOp.cGE)
        {
            if (IsNumber(clrLeft) && IsNumber(clrRight))
                return true;
            if (IsEnum(clrLeft) && IsEnum(clrRight))
                return true;                
        }
        
        // These ops can't be overloaded, so they had better
        // match a default type
        if (op == BinaryOp.cAnd || op == BinaryOp.cOr)
        {
            return true;        
        }
        
        return false;
    }
    
    // Determine the CLR type of this expression
    // If we're a predefined op, then this is given by the C# spec.
    // If we're an overloaded op, then this is the return type of the method
    // that we resolve to.
    protected override Type CalcCLRTypeHelper(ISemanticResolver s)
    {
        
        
        switch(this.Op)
        {   
            // Special case for string.concat
            case BinaryOp.cAdd: 
                if (Left.CLRType == typeof(string) || Right.CLRType == typeof(string))
                    return typeof(string);
                return typeof(int);
            
            case BinaryOp.cSub: return typeof(int);
            case BinaryOp.cMul: return typeof(int);
            case BinaryOp.cDiv: return typeof(int);
            case BinaryOp.cMod: return typeof(int);
        
            case BinaryOp.cAnd: return typeof(bool);
            case BinaryOp.cOr: return typeof(bool);
                    
            case BinaryOp.cEqu: return typeof(bool);
            case BinaryOp.cNeq: return typeof(bool);
            case BinaryOp.cLT: return typeof(bool);
            case BinaryOp.cGT: return typeof(bool);
            case BinaryOp.cLE: return typeof(bool);
            case BinaryOp.cGE: return typeof(bool);
            
            case BinaryOp.cBitwiseAnd:  return Left.CLRType;
            case BinaryOp.cBitwiseOr:   return Left.CLRType;
            case BinaryOp.cBitwiseXor:  return Left.CLRType;
            
            case BinaryOp.cShiftLeft:   return Left.CLRType;
            case BinaryOp.cShiftRight:  return Left.CLRType;
        }

        Debug.Assert(false, "Unknown binary op:"+this.Op.ToString());

        return null;
    }
#endregion    
    
    // Code generation
    public override void GenerateAsRight(CodeGen.EmitCodeGen gen)
    {
        gen.Generate(this);
    }    
    
#region Checks    
    //-----------------------------------------------------------------------------
    // Debugging check
    //-----------------------------------------------------------------------------
    public override void DebugCheck(ISemanticResolver s)
    {
        Debug.Assert(m_left != null);
        Debug.Assert(m_right != null);
        
        CalcCLRType(s);
                
        m_left.DebugCheck(s);
        m_right.DebugCheck(s);
    }
    
    // Dump as XML
    public override void Dump(XmlWriter o)
    {
        o.WriteStartElement("BinaryExp");
        o.WriteAttributeString("op", m_op.ToString());
        m_left.Dump(o);
        m_right.Dump(o);
        o.WriteEndElement();
    }   
    
    public override void ToSource(System.CodeDom.Compiler.IndentedTextWriter sb)    
    {
        sb.Write('(');
        m_left.ToSource(sb);
        sb.Write(OpName(this.m_op));
        m_right.ToSource(sb);
        sb.Write(')');        
    }
#endregion    
}

//-----------------------------------------------------------------------------    
// Unary operations
//-----------------------------------------------------------------------------        
public class UnaryExp : Exp
{
    public enum UnaryOp
    {
        cNegate,
        cNot,
        cPreInc,
        cPostInc,
        cPreDec,
        cPostDec
    }

    public UnaryExp(Exp left, UnaryOp op)

⌨️ 快捷键说明

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