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

📄 objexpast.cs

📁 charp compiler
💻 CS
📖 第 1 页 / 共 5 页
字号:
        // If we changed nodes, then resolve the new one.
        // If we didn't change, then don't resolve again (else we have stack-overflow)
        if (e != this)
            Exp.ResolveExpAsRight(ref e, s);
            
        e.SetLocation(this.Location);
        return e;
    }
    
    
    // An ObjExp is just a temporary node. But that's the best a Context-Free parse can
    // do. So now that we're building a symbol table, we can do a Context-Sensitive resolution
    // and figure out what type of node this really is.
    public Exp GetResolvedNode(ISemanticResolver s)
    {
        string stText = this.m_strId.Text;
        // Left must already be resolved, then we resolve right in the context of left
        Debug.Assert(m_left != null);
        Exp eResolved = null;
                   
        // @todo, what if left is a NullExp?                       
        if (m_left is NamespaceExp)
        {
            // We're either a nested namespace or a class
            NamespaceEntry n = (m_left as NamespaceExp).Symbol;
            SymEntry sym = n.ChildScope.LookupSymbol(stText);
            if (sym is NamespaceEntry)
            {
                eResolved = new NamespaceExp(sym as NamespaceEntry);
            }
            else if (sym is TypeEntry)
            {
                eResolved = new TypeExp(sym as TypeEntry);
            } else {
                //ThrowError_UndefinedSymbolInNamespace(s, n, m_strId);            
                ThrowError(SymbolError.UndefinedSymbolInNamespace(n, m_strId));
            }
        }
        
        // Check for statics
        else if (m_left is TypeExp)
        {
            TypeEntry t = ((TypeExp) m_left).Symbol;
            t.EnsureResolved(s);
            SymEntry sym = t.MemberScope.LookupSymbol(stText);
            if (sym is FieldExpEntry)
            {
                Debug.Assert(((FieldExpEntry) sym).IsStatic);
                eResolved = new FieldExp(sym as FieldExpEntry, null); // static
            }
            
            else if (sym is PropertyExpEntry)
            {
                eResolved = new PropertyExp(sym as PropertyExpEntry, null);
            } 
            
            else if (sym is EventExpEntry)
            {
                eResolved = new EventExp(sym as EventExpEntry, null);
            }
            
            // Allow nested types
            else if (sym is TypeEntry)
            {
                eResolved = new TypeExp(sym as TypeEntry);
            }
            
            else 
            {
                // Must be a method. The node transform occurs higher up though.
                Debug.Assert((sym = t.LookupMethodHeader(stText)) != null);                
                eResolved = this;
            }
            
            if (eResolved == null) {
                //ThrowError_UndefinedSymbolInType(s, t, m_strId);
                ThrowError(SymbolError.UndefinedSymbolInType(t, m_strId));
            }
        }
        
        // m_left is a variable, and we're doing an instance member dereference
        else {
            TypeEntry t = null;
            
            t = s.ResolveCLRTypeToBlueType(this.m_left.CLRType);
            t.EnsureResolved(s);
                       
            Scope scope = t.MemberScope;
            
            // @todo - broken for an interface. IA : IB, scope for IA doesn't link to IB.
            SymEntry sym = scope.LookupSymbol(stText);
            if (sym is FieldExpEntry)
            {
                eResolved = new FieldExp(sym as FieldExpEntry, this.m_left);
            } 
            else if (sym is PropertyExpEntry)
            {
                eResolved = new PropertyExp(sym as PropertyExpEntry, this.m_left);
            }
            
            else if (sym is EventExpEntry)
            {
                eResolved = new EventExp(sym as EventExpEntry, this.m_left);            
            }
            
            else 
            {
                // Must be a method. The node transform occurs higher up though.
                sym = t.LookupMethodHeader(stText);
                if (sym != null)
                    eResolved = this;
            }
            
            if (eResolved == null) 
            {                
                ThrowError(SymbolError.UndefinedSymbolInType(t, m_strId));
            }
        }
        
        
        Debug.Assert(eResolved != null);
        return eResolved;
        
    }

#endregion

#region Checks
    public override void DebugCheck(ISemanticResolver s)
    {
        Debug.Assert(false, "Temporary node still in Final pass");
    }
    
    public override void Dump(XmlWriter o)
    {
        
    }
    
    public override void ToSource(System.CodeDom.Compiler.IndentedTextWriter sb)    
    {
        this.m_left.ToSource(sb);
        sb.Write(".'{0}'", this.Id.Text);   
    }
#endregion    
    
}


//-----------------------------------------------------------------------------
//Method Call exp
//MethodCall-> LValue '.' id '(' paramlist ')' 
//MethodCall-> id '(' paramlist ')' // no LValue, implied 'this'
//-----------------------------------------------------------------------------
public class MethodCallExp : StatementExp
{
#region Construction
    public MethodCallExp(
        Exp e, // may be null,
        Identifier id,
        ArgExp [] arParams
    )
    {   
    // m_objExp may be null _until_ we resolve this. And then it's either
    // going to the implied 'this' ptr, a global func or a static func.
        m_objExp = e;
        m_idName = id;
        m_arParams = (arParams == null) ? new ArgExp[0] : arParams;
        
        
        // @todo - set in parser
        m_filerange = id.Location;        
    }
    
    // Use this when we already have a static method to call
    // and we already have the symbols
    public MethodCallExp(
        Exp eInstance, // null if static       
        MethodExpEntry  symMethod,
        ArgExp [] arParams,
        ISemanticResolver s
    )
    {
        this.m_idName = new Identifier(symMethod.Name);
        m_arParams = arParams;
        m_symbol = symMethod;
        
        // Spoof Left
        if (eInstance == null)
        {
            //m_objExp = new SimpleObjExp(symMethod.SymbolClass.Name);
            m_objExp = new TypeExp(symMethod.SymbolClass);
        }
        else
            m_objExp = eInstance;
            
        Exp.ResolveExpAsRight(ref m_objExp, s);

        // Resolve args, just in case
        foreach(ArgExp eArg in arParams)
        {
            Exp e = eArg;
            Exp.ResolveExpAsRight(ref e, s);
            Debug.Assert(e == eArg);
        }   
        
        //ResolveAsExpEntry(m_symbol, s);
        CalcCLRType(s);
    }
    
#endregion

#region Checks
    //-----------------------------------------------------------------------------
    // Debugging check
    //-----------------------------------------------------------------------------
    public override void DebugCheck(ISemanticResolver s)
    {
        Debug.Assert(Symbol != null);
        Debug.Assert(m_symbol.RetType.CLRType == base.CalcCLRType(s));
        Debug.Assert(m_symbol.m_strName == this.m_idName.Text);
                
        Debug.Assert(m_symbol.Info != null);
        
        //Debug.Assert(m_mode == ObjExp.Mode.cExpEntry);
                
        m_objExp.DebugCheck(s);
        
        foreach(ArgExp e in ParamExps)
        {
            e.DebugCheck(s);
        }
                        
    }
    
    public override void ToSource(System.CodeDom.Compiler.IndentedTextWriter sb)    
    {
        #if true
        if (this.m_objExp == null)        
            sb.Write(this.Symbol.SymbolClass.FullName);
        else
            m_objExp.ToSource(sb);
                
        sb.Write('.');
        sb.Write(this.Symbol.Name);
        #endif
        
        sb.Write('(');
        bool fFirst = true;
        foreach(ArgExp a in m_arParams)
        {
            if (!fFirst)
                sb.Write(',');
            a.ToSource(sb);
            
            fFirst = false;
        }
        sb.Write(')');
    }
    
    // Dump as XML
    public override void Dump(XmlWriter o)
    {
        o.WriteStartElement("MethodCallExp");
        o.WriteAttributeString("name", m_idName.Text);
            
        if (m_symbol != null)
            o.WriteAttributeString("symbol", m_symbol.ToString());
    
        if (m_objExp != null)
            m_objExp.Dump(o);
        
        o.WriteStartElement("parameters");    
        foreach(ArgExp e in m_arParams)
        {
            e.Dump(o);
        }
        o.WriteEndElement();
                
        o.WriteEndElement();
    }        
#endregion Checks

#region Properties & Data
    Exp m_objExp;    
    public Exp LeftObjExp
    {
        get { return m_objExp; }
    }

    ArgExp [] m_arParams;
    
    //readonly string m_strName;
    readonly Identifier m_idName;
    
    public MethodExpEntry m_symbol;

    public ArgExp [] ParamExps
    {
        get { return m_arParams; }
    }

    public MethodExpEntry Symbol
    {
        get { return m_symbol; }
    }
    
    //bool m_fIsVarArg;
    /*
    public bool IsVarArg
    {
        get { return m_fIsVarArg; }
    }*/

    // Should codegen make this a static call or an instance call?
    public bool IsStaticCall
    {
        get { return m_symbol.IsStatic; }
    }
    
    bool m_fIsNotPolymorphic;
    public bool IsNotPolymorphic
    {
        get { return m_fIsNotPolymorphic; }
    }
#endregion

#region Resolution
    // The type of a method expression is its return type.
    protected override Type CalcCLRTypeHelper(ISemanticResolver s)
    {
        return this.Symbol.CLRType;
    }
    
    // Semantic resolution
    protected override Exp ResolveExpAsRight(ISemanticResolver s)
    {   
        // Only resolve once.     
        if (m_symbol != null)
            return this;
            
        // First, resolve our parameters (because of overloading)
        // We need to know the URT types for our parameters
        // in order to resolve between overloaded operators
        
        Type [] alParamTypes = new Type[m_arParams.Length];
        
        
        for(int i = 0; i < m_arParams.Length; i++)        
        {
            Exp e = m_arParams[i];
            ResolveExpAsRight(ref e, s);
            Debug.Assert(e == m_arParams[i]);
            
            Type tParam = e.CLRType;
            
            //if ((tParam !=null) && tParam.IsByRef)
            //    tParam = tParam.GetElementType();
            
            alParamTypes[i] = tParam;
            //Debug.Assert(alParamTypes[i] != null);
            
        }   
        
        TypeEntry tCur = s.GetCurrentClass();    
        TypeEntry tLeft = null; // Type to lookup in   
        
        // Is this a 'base' access?
        // Convert to the real type and set a non-virtual flag
        if (m_objExp is SimpleObjExp)
        {
            SimpleObjExp e = m_objExp as SimpleObjExp;
            if (e.Name.Text == "base")
            {
                // Set the scope that we lookup in.
                tLeft = tCur.Super;
                
                // Still need to resolve the expression.
                m_objExp = new SimpleObjExp("this");               
                                               
                m_fIsNotPolymorphic = true;
            }
        }
        
#if true
        // See if we have a delegate here
        Exp eDelegate = null;
        if (m_objExp == null)
        {
            Exp e = new SimpleObjExp(m_idName);
            Exp.ResolveExpAsRight(ref e, s);
            if (!(e is SimpleObjExp))                
                eDelegate = e;
        } else {
            // If it's an interface, then we know we can't have a delegate field on it, 
            // so short-circuit now. 
            Exp.ResolveExpAsRight(ref m_objExp, s);
            if (!m_objExp.CLRType.IsInterface)
            {                
                Exp e = new DotObjExp(m_objExp, m_idName);
                Exp.ResolveExpAsRight(ref e, s);
                if (!(e is DotObjExp))                
                    eDelegate = e;        
            }
        }

        if (eDelegate != null)
        {
            if (!DelegateDecl.IsDelegate(eDelegate.CLRType))
            {
                //Debug.Assert(false, "@todo - " + m_strName + " is not a delegate or function"); // @todo - legit
                // Just fall through for now, method resolution will decide if this is a valid function
            } else 
            {            
                Exp e = new MethodCallExp(
                    eDelegate, 
                    new Identifier("Invoke"), 
                    this.m_arParams
                );
                
                Exp.ResolveExpAsRight(ref e, s);
                return e;        
            }
        }        
#endif    
        // No delegate, carry on with a normal function call
                        
        // If there's no objexp, then the function is a method
        // of the current class. 
        // make it either a 'this' or a static call
        if (m_objExp == null)
        {   
            // Lookup
            bool fIsVarArgDummy;
            MethodExpEntry sym = tCur.LookupMethod(s, m_idName, alParamTypes, out fIsVarArgDummy);
            
            if (sym.IsStatic)
            {                

⌨️ 快捷键说明

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