Exemplo n.º 1
0
        //------------------------------------------------------------
        // CreateGetTypeFromHandleMethodSym
        //
        /// <summary>
        /// <para>Defined in FuncBindUtil.cs</para>
        /// </summary>
        /// <param name="treeNode"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        internal METHSYM CreateGetTypeFromHandleMethodSym(BASENODE treeNode)
        {
            if (GetTypeFromHandleMethodSym != null)
            {
                return(GetTypeFromHandleMethodSym);
            }

            // System.RuntimeTypeHandle
            TYPESYM handleTypeSym = this.GetRequiredPredefinedType(PREDEFTYPE.TYPEHANDLE);

            DebugUtil.Assert(handleTypeSym != null);

            TypeArray paramArray = new TypeArray();

            paramArray.Add(handleTypeSym);
            paramArray = Compiler.MainSymbolManager.AllocParams(paramArray);

            GetTypeFromHandleMethodSym = FindPredefMeth(
                treeNode,
                PREDEFNAME.GETTYPEFROMHANDLE,
                this.GetRequiredPredefinedType(PREDEFTYPE.TYPE),
                paramArray,
                true,
                MemLookFlagsEnum.None);
            DebugUtil.Assert(GetTypeFromHandleMethodSym != null);

            return(GetTypeFromHandleMethodSym);
        }
Exemplo n.º 2
0
        //------------------------------------------------------------
        // FUNCBREC.EnsureNubHasValue
        //
        /// <summary>
        /// Make sure the HasValue property of System.Nullable&lt;T&gt; is appropriate (and return it).
        /// </summary>
        /// <param name="treeNode"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        private PROPSYM EnsureNubHasValue(BASENODE treeNode)
        {
            PROPSYM propSym = Compiler.MainSymbolManager.NullableHasValuePropertySym;

            if (propSym == null)
            {
                AGGSYM nubAggSym = Compiler.GetOptPredefAggErr(PREDEFTYPE.G_OPTIONAL, true);
                if (nubAggSym == null)
                {
                    return(null);
                }
                string name = Compiler.NameManager.GetPredefinedName(PREDEFNAME.HASVALUE);

                SYM sym = Compiler.MainSymbolManager.LookupAggMember(
                    name, nubAggSym, SYMBMASK.PROPSYM);
                propSym = sym as PROPSYM;
                if (propSym == null ||
                    propSym.IsStatic ||
                    propSym.Access != ACCESS.PUBLIC ||
                    propSym.ParameterTypes.Count > 0 ||
                    !propSym.ReturnTypeSym.IsPredefType(PREDEFTYPE.BOOL) ||
                    propSym.GetMethodSym == null)
                {
                    Compiler.Error(treeNode, CSCERRID.ERR_MissingPredefinedMember,
                                   new ErrArg(nubAggSym), new ErrArg(name));
                    return(null);
                }
                Compiler.MainSymbolManager.NullableHasValuePropertySym = propSym;
            }

            return(propSym);
        }
Exemplo n.º 3
0
        //------------------------------------------------------------
        // CLSDREC.SetForPartialMethod
        //
        /// <summary></summary>
        /// <param name="treeNode"></param>
        /// <param name="partialMethSym">the partial method</param>
        /// <param name="otherMethSym">the other method with the same signiture</param>
        /// <param name="errorID"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        internal bool CheckForDulicatePartialMethod(
            BASENODE treeNode,
            METHSYM partialMethSym,
            METHSYM otherMethSym)
        {
            if (partialMethSym == null || otherMethSym == null)
            {
                return(true);
            }

            if (!otherMethSym.IsPartialMethod)
            {
                Compiler.Error(
                    treeNode,
                    CSCERRID.ERR_MemberAlreadyExists,
                    new ErrArg(partialMethSym),
                    new ErrArg(partialMethSym.ClassSym));
                return(false);
            }

            if (!partialMethSym.HasNoBody && !otherMethSym.HasNoBody)
            {
                Compiler.Error(
                    treeNode,
                    CSCERRID.ERR_MultiplePartialMethodImplementation);
                return(false);
            }

            return(true);
        }
Exemplo n.º 4
0
        //------------------------------------------------------------
        // FUNCBREC.BindNubValue
        //
        /// <summary>
        /// Create an expr for exprSrc.Value where exprSrc->type is a NUBSYM.
        /// </summary>
        /// <param name="treeNode"></param>
        /// <param name="srcExpr"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        private EXPR BindNubValue(BASENODE treeNode, EXPR srcExpr)
        {
            DebugUtil.Assert(srcExpr != null && srcExpr.TypeSym.IsNUBSYM);

            // For new T?(x), the answer is x.
            if (IsNubCtor(srcExpr))
            {
                DebugUtil.Assert(
                    (srcExpr as EXPRCALL).ArgumentsExpr != null &&
                    (srcExpr as EXPRCALL).ArgumentsExpr.Kind != EXPRKIND.LIST);
                return((srcExpr as EXPRCALL).ArgumentsExpr);
            }

            TYPESYM    baseTypeSym = (srcExpr.TypeSym as NUBSYM).BaseTypeSym;
            AGGTYPESYM ats         = (srcExpr.TypeSym as NUBSYM).GetAggTypeSym();

            if (ats == null)
            {
                return(NewError(treeNode, baseTypeSym));
            }
            compiler.EnsureState(ats, AggStateEnum.Prepared);

            PROPSYM propertySym = compiler.MainSymbolManager.NullableValuePropertySym;

            if (propertySym == null)
            {
                string name = compiler.NameManager.GetPredefinedName(PREDEFNAME.CAP_VALUE);

                propertySym = compiler.MainSymbolManager.LookupAggMember(
                    name,
                    ats.GetAggregate(),
                    SYMBMASK.PROPSYM) as PROPSYM;
                if (propertySym == null ||
                    propertySym.IsStatic ||
                    propertySym.Access != ACCESS.PUBLIC ||
                    propertySym.ParameterTypes.Count > 0 ||
                    !propertySym.ReturnTypeSym.IsTYVARSYM ||
                    propertySym.GetMethodSym == null)
                {
                    compiler.Error(
                        treeNode,
                        CSCERRID.ERR_MissingPredefinedMember,
                        new ErrArg(ats),
                        new ErrArg(name));
                    return(NewError(treeNode, baseTypeSym));
                }
                compiler.MainSymbolManager.NullableValuePropertySym = propertySym;
            }

            CheckFieldUse(srcExpr, true);

            EXPRPROP propertyExpr = NewExpr(treeNode, EXPRKIND.PROP, baseTypeSym) as EXPRPROP;

            propertyExpr.SlotPropWithType.Set(propertySym, ats);
            propertyExpr.GetMethodWithType.Set(propertySym.GetMethodSym, ats);
            propertyExpr.ArgumentsExpr = null;
            propertyExpr.ObjectExpr    = srcExpr;

            return(propertyExpr);
        }
Exemplo n.º 5
0
        //------------------------------------------------------------
        // ERRLOC Constructor (3)
        //
        /// <para>Constructor.</para>
        /// <para>Get the current position from the BASENODE argument and
        /// mapping information from INFILESYM.SourceData of BSYMMGR.</para>
        /// <param name="symmgr"></param>
        /// <param name="node"></param>
        //------------------------------------------------------------
        internal ERRLOC(BSYMMGR symmgr, BASENODE node, bool fullPath)
        {
            if (node != null)
            {
                DebugUtil.Assert(symmgr != null);

                string    inputFileName = node.GetContainingFileName(fullPath);
                INFILESYM inputFile     = symmgr.FindInfileSym(inputFileName);

                sourceFileName    = inputFileName;
                sourceMapFileName = inputFileName;

                if (inputFile != null)
                {
                    sourceData = inputFile.SourceData;
                    SetLine(node);
                    SetStart(node);
                    SetEnd(node);
                    mapStartPos = (startPos != null ? startPos.Clone() : null);
                    mapEndPos   = (endPos != null ? endPos.Clone() : null);

                    string sd;
                    bool   bd1, bd2;
                    sourceData.Module.MapLocation(mapStartPos, out sourceMapFileName, out bd1, out bd2);
                    sourceData.Module.MapLocation(mapEndPos, out sd, out bd1, out bd2);
                    return;
                }
            }
        }
Exemplo n.º 6
0
        //------------------------------------------------------------
        // FUNCBREC.AddSideEffects
        //
        /// <summary>
        /// <para>Add sideExpr to baseExpr as a side effect.</para>
        /// <para>If isPre is true, sideExpr is evaluated before baseExpr.</para>
        /// <para>If sideExpr is NULL or contains no side effects, just returns baseExpr.</para>
        /// <para>If no side effect, return baseExpr.
        /// Otherwise create and return an EXPRBINOP instance of
        /// whose operands are sideExpr and baseExpr.</para>
        /// </summary>
        /// <param name="treeNode"></param>
        /// <param name="baseExpr"></param>
        /// <param name="sideExpr"></param>
        /// <param name="isPre"></param>
        /// <param name="forceNonConst"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        private EXPR AddSideEffects(
            BASENODE treeNode,
            EXPR baseExpr,
            EXPR sideExpr,
            bool isPre,
            bool forceNonConst) // = false
        {
            if (sideExpr == null)
            {
                return(baseExpr);
            }

            if (!sideExpr.HasSideEffects(Compiler))
            {
                // Make sure it's not an lvalue or constant (unless sideExpr is a constant and !forceNonConst).
                if (((baseExpr.Flags & EXPRFLAG.LVALUE) == 0) &&
                    (baseExpr.Kind != EXPRKIND.CONSTANT || sideExpr.Kind == EXPRKIND.CONSTANT && !forceNonConst))
                {
                    return(baseExpr);
                }
                return(NewExprBinop(
                           treeNode,
                           EXPRKIND.SEQUENCE,
                           baseExpr.TypeSym,
                           NewExpr(treeNode, EXPRKIND.NOOP, GetVoidType()),
                           baseExpr));
            }
            if (isPre)
            {
                return(NewExprBinop(treeNode, EXPRKIND.SEQUENCE, baseExpr.TypeSym, sideExpr, baseExpr));
            }
            return(NewExprBinop(treeNode, EXPRKIND.SEQREV, baseExpr.TypeSym, baseExpr, sideExpr));
        }
Exemplo n.º 7
0
        //------------------------------------------------------------
        // ERRLOC Constructor (2)
        //
        /// <summary>
        /// <para>Constructor.</para>
        /// <para>Get the current position from the BASENODE argument and
        /// mapping information from INFILESYM.SourceData.</para>
        /// </summary>
        /// <param name="inputFile"></param>
        /// <param name="node"></param>
        //------------------------------------------------------------
        internal ERRLOC(INFILESYM inputFile, BASENODE node, bool fullPath)
        {
            DebugUtil.Assert(inputFile != null);

            sourceData = inputFile.SourceData;

            sourceFileName    = (fullPath ? inputFile.FullName : inputFile.Name);
            sourceMapFileName = inputFile.Name;

            if (node != null)
            {
                SetLine(node);
                SetStart(node);
                this.endPos = new POSDATA();    //endPos.SetUninitialized();
                SetEnd(node);
                mapStartPos = (startPos != null ? startPos.Clone() : null);
                mapEndPos   = (endPos != null ? endPos.Clone() : null);

                string sd;       // dummy
                bool   bd1, bd2; // dummy

                // mapStart、mapEnd の行番号をマップ先のもので置き換え、ファイル名を取得する。
                sourceData.Module.MapLocation(mapStartPos, out sourceMapFileName, out bd1, out bd2);
                sourceData.Module.MapLocation(mapEndPos, out sd, out bd1, out bd2);
            }
        }
Exemplo n.º 8
0
        //------------------------------------------------------------
        // CSourceData.LookupNode
        //------------------------------------------------------------
        //STDMETHODIMP CSourceData::LookupNode (
        //    NAME *pKey, long iOrdinal, BASENODE **ppNode, long *piGlobalOrdinal)
        //virtual internal int LookupNode(
        //    ref string pKey, int iOrdinal, ref BASENODE ppNode, ref int piGlobalOrdinal)
        //{
        //    return sourceModuleBase.LookupNode (this, pKey, iOrdinal, ppNode, piGlobalOrdinal);
        //}

        //------------------------------------------------------------
        // CSourceData.GetNodeKeyOrdinal
        //------------------------------------------------------------
        //STDMETHODIMP CSourceData::GetNodeKeyOrdinal (BASENODE *pNode, NAME **ppKey, long *piKeyOrdinal)
        //virtual internal int GetNodeKeyOrdinal(BASENODE pNode, ref string ppKey, ref int piKeyOrdinal)
        //{
        //    return sourceModuleBase.GetNodeKeyOrdinal (this, pNode, ppKey, piKeyOrdinal);
        //}

        //------------------------------------------------------------
        // CSourceData.GetGlobalKeyArray
        //------------------------------------------------------------
        //STDMETHODIMP CSourceData::GetGlobalKeyArray (KEYEDNODE *pKeyedNodes, long iSize, long *piCopied)
        //virtual internal int GetGlobalKeyArray(KEYEDNODE pKeyedNodes, int iSize, ref int piCopied)
        //{
        //    return sourceModuleBase.GetGlobalKeyArray (this, pKeyedNodes, iSize, piCopied);
        //}

        //------------------------------------------------------------
        // CSourceData.ParseForErrors
        //------------------------------------------------------------
        //STDMETHODIMP CSourceData::ParseForErrors ()
        //virtual internal int ParseForErrors()
        //{
        //    return sourceModuleBase.ParseForErrors (this);
        //}

        //------------------------------------------------------------
        // CSourceData.FindLeafNode
        //------------------------------------------------------------
        //STDMETHODIMP CSourceData::FindLeafNode (
        //  const POSDATA pos, BASENODE **ppNode, ICSInteriorTree **ppTree)
        //virtual internal int FindLeafNode(POSDATA pos, ref BASENODE ppNode, ref CInteriorTree ppTree)
        //{
        //    return FindLeafNodeEx(pos, EF_FULL, ppNode, ppTree);
        //}

        //------------------------------------------------------------
        // CSourceData.FindLeafNodeForToken
        //------------------------------------------------------------
        //STDMETHODIMP CSourceData::FindLeafNodeForToken (
        //  long iToken, BASENODE **ppNode, ICSInteriorTree **ppTree)
        //virtual internal int FindLeafNodeForToken(
        //    int iToken, ref BASENODE ppNode, ref CInteriorTree ppTree)
        //{
        //    return FindLeafNodeForTokenEx(iToken, EF_FULL, ppNode, ppTree);
        //}

        //------------------------------------------------------------
        // CSourceData.FindLeafNodeEx
        //------------------------------------------------------------
        //STDMETHODIMP CSourceData::FindLeafNodeEx (
        //    const POSDATA pos, ExtentFlags flags, BASENODE **ppNode, ICSInteriorTree **ppTree)
        //virtual internal int FindLeafNodeEx(
        //    POSDATA pos, ExtentFlags flags, ref BASENODE ppNode, ref CInteriorTree ppTree)
        //{
        //    return sourceModuleBase.FindLeafNodeEx (this, pos, flags, ppNode, ppTree);
        //}

        //------------------------------------------------------------
        // CSourceData.FindLeafNodeForTokenEx
        //------------------------------------------------------------
        //STDMETHODIMP CSourceData::FindLeafNodeForTokenEx (
        //  long iToken, ExtentFlags flags, BASENODE **ppNode, ICSInteriorTree **ppTree)
        //virtual internal int FindLeafNodeForTokenEx(
        //    int iToken, ExtentFlags flags, ref BASENODE ppNode, ref CInteriorTree ppTree)
        //{
        //    return sourceModuleBase.FindLeafNodeForTokenEx (this, iToken, flags, ppNode, ppTree);
        //}

        //------------------------------------------------------------
        // CSourceData.GetExtent
        //------------------------------------------------------------
        //virtual internal int GetExtent(BASENODE pNode, POSDATA pposStart, POSDATA pposEnd)
        //{
        //}

        //STDMETHODIMP CSourceData::GetExtent(BASENODE *pNode, POSDATA *pposStart, POSDATA *pposEnd) {
        //    return GetExtentEx( pNode, pposStart, pposEnd, EF_FULL);
        //};

        //------------------------------------------------------------
        // CSourceData.GetExtentEx
        //
        /// <summary></summary>
        /// <param name="node"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="flags"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        virtual internal bool GetExtentEx(
            BASENODE node,
            POSDATA start,
            POSDATA end,
            ExtentFlags flags)
        {
            return(sourceModuleBase.GetExtent(node, start, end, flags));
        }
Exemplo n.º 9
0
        //------------------------------------------------------------
        // FUNCBREC.BindImplicitlyTypedArrayInitCore
        //
        /// <summary></summary>
        /// <param name="treeUnOpNode"></param>
        /// <param name="elementTypeSym"></param>
        /// <param name="dimList"></param>
        /// <param name="dimIndex"></param>
        /// <param name="topArgList"></param>
        //------------------------------------------------------------
        internal void BindImplicitlyTypedArrayInitCore(
            UNOPNODE treeUnOpNode,
            ref TYPESYM elementTypeSym,
            List <int> dimList,
            int dimIndex,
            ref EXPR topArgList)
        {
            int  count       = 0;
            EXPR lastArgList = null;

            BASENODE node = treeUnOpNode.Operand;

            while (node != null)
            {
                BASENODE itemNode;
                if (node.Kind == NODEKIND.LIST)
                {
                    itemNode = node.AsLIST.Operand1.AsBASE;
                    node     = node.AsLIST.Operand2;
                }
                else
                {
                    itemNode = node.AsBASE;
                    node     = null;
                }
                count++;

                EXPR expr = BindExpr(itemNode, BindFlagsEnum.RValueRequired);
                if (elementTypeSym == null ||
                    elementTypeSym.Kind == SYMKIND.IMPLICITTYPESYM)
                {
                    elementTypeSym = expr.TypeSym;
                }
                else if (CanConvert(elementTypeSym, expr.TypeSym, ConvertTypeEnum.STANDARD))
                {
                    elementTypeSym = expr.TypeSym;
                }
                else if (!CanConvert(expr.TypeSym, elementTypeSym, ConvertTypeEnum.STANDARD))
                {
                    // do nothing here.
                }

                NewList(expr, ref topArgList, ref lastArgList);
                //exprList.Add(expr);
            }

            if (dimList[dimIndex] != -1)
            {
                if (dimList[dimIndex] != count)
                {
                    Compiler.Error(treeUnOpNode, CSCERRID.ERR_InvalidArray);
                }
            }
            else
            {
                dimList[dimIndex] = count;
            }
        }
Exemplo n.º 10
0
        //------------------------------------------------------------
        // CInteriorTree.Initialize
        //
        /// <summary>
        /// Set this.interiorNode and return true.
        /// </summary>
        /// <param name="data"></param>
        /// <param name="node"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        internal bool Initialize(CSourceData data, BASENODE node)
        {
            sourceData = data;
#if DEBUG
            debugThread = Thread.CurrentThread;
#endif
            interiorNode = data.Module.GetInteriorNode(data, node);
            return(true);
        }
Exemplo n.º 11
0
 //------------------------------------------------------------
 // CLSDREC.IsAutoImplementedAccessor
 //
 /// <summary></summary>
 /// <param name="methodSym"></param>
 /// <returns></returns>
 //------------------------------------------------------------
 internal static bool IsAutoImplementedAccessor(BASENODE node)
 {
     if (node == null ||
         node.Kind != NODEKIND.ACCESSOR)
     {
         return(false);
     }
     return((node as ACCESSORNODE).IsAutoImplemented);
 }
Exemplo n.º 12
0
        //------------------------------------------------------------
        // CLSDREC.SetForPartialMethod
        //
        /// <summary></summary>
        /// <param name="treeNode"></param>
        /// <param name="methodSym"></param>
        //------------------------------------------------------------
        internal void SetForPartialMethod(BASENODE treeNode, METHSYM methodSym)
        {
            if (!IsPartialMethod(treeNode))
            {
                return;
            }

            methodSym.IsPartialMethod = true;
            methodSym.HasNoBody       = ((treeNode.NodeFlagsEx & NODEFLAGS.EX_METHOD_NOBODY) != 0);
        }
Exemplo n.º 13
0
        //private ~CInteriorTree();

        //------------------------------------------------------------
        // CInteriorTree.CreateInstance
        //
        /// <summary>
        /// Create a CInteriorTree instance and initialize it with the arguments.
        /// </summary>
        /// <param name="data"></param>
        /// <param name="node"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        static internal CInteriorTree CreateInstance(CSourceData data, BASENODE node)
        {
            CInteriorTree tree = new CInteriorTree();

            if (tree.Initialize(data, node))
            {
                return(tree);
            }
            return(null);
        }
Exemplo n.º 14
0
        //------------------------------------------------------------
        // FUNCBREC.BindNubNew
        //
        /// <summary>
        /// Create an expr for new T?(exprSrc) where T is exprSrc-&gt;type.
        /// </summary>
        /// <param name="treeNode"></param>
        /// <param name="srcExpr"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        private EXPR BindNubNew(BASENODE treeNode, EXPR srcExpr)
        {
            DebugUtil.Assert(srcExpr != null);

            // Create a NUBSYM instance whose base bype is represented by srcExpr.TypeSym.
            NUBSYM nubSym = Compiler.MainSymbolManager.GetNubType(srcExpr.TypeSym);

            // Get a TYPESYM instance representing Nullable<> for nubSym.
            AGGTYPESYM aggTypeSym = nubSym.GetAggTypeSym();

            if (aggTypeSym == null)
            {
                return(NewError(treeNode, nubSym));
            }
            Compiler.EnsureState(aggTypeSym, AggStateEnum.Prepared);

            METHSYM methSym = Compiler.MainSymbolManager.NullableCtorMethodSym;

            if (methSym == null)
            {
                string name = Compiler.NameManager.GetPredefinedName(PREDEFNAME.CTOR);

                for (SYM sym = Compiler.MainSymbolManager.LookupAggMember(name, aggTypeSym.GetAggregate(), SYMBMASK.ALL);
                     ;
                     sym = sym.NextSameNameSym)
                {
                    if (sym == null)
                    {
                        Compiler.Error(treeNode, CSCERRID.ERR_MissingPredefinedMember,
                                       new ErrArg(aggTypeSym), new ErrArg(name));
                        return(NewError(treeNode, nubSym));
                    }
                    if (sym.IsMETHSYM)
                    {
                        methSym = sym as METHSYM;
                        if (methSym.ParameterTypes.Count == 1 && methSym.ParameterTypes[0].IsTYVARSYM &&
                            methSym.Access == ACCESS.PUBLIC)
                        {
                            break;
                        }
                    }
                }
                Compiler.MainSymbolManager.NullableCtorMethodSym = methSym;
            }

            EXPRCALL resExpr = NewExpr(treeNode, EXPRKIND.CALL, nubSym) as EXPRCALL;

            resExpr.MethodWithInst.Set(methSym, aggTypeSym, BSYMMGR.EmptyTypeArray);
            resExpr.ArgumentsExpr = srcExpr;
            resExpr.ObjectExpr    = null;
            resExpr.Flags        |= EXPRFLAG.NEWOBJCALL | EXPRFLAG.CANTBENULL;

            return(resExpr);
        }
Exemplo n.º 15
0
        //------------------------------------------------------------
        // CLSDREC.IsPartialMethod
        //
        /// <summary></summary>
        /// <param name="node"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        internal bool IsPartialMethod(BASENODE treeNode)
        {
            DebugUtil.Assert(treeNode != null);

            if (treeNode.Kind != NODEKIND.METHOD)
            {
                return(false);
            }

            return((treeNode.Flags & NODEFLAGS.MOD_PARTIAL) != 0);
        }
Exemplo n.º 16
0
        //------------------------------------------------------------
        // FUNCBREC.BindNubFetchAndFree
        //
        /// <summary>
        /// If the given slot has a temp associated with it,
        /// constructs a reverse sequence for loading the value and freeing the temp.
        /// Otherwise, just returns the value expr.
        /// </summary>
        /// <param name="treeNode"></param>
        /// <param name="nubInfo"></param>
        /// <param name="iexpr"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        private EXPR BindNubFetchAndFree(BASENODE treeNode, ref NubInfo nubInfo, int iexpr)
        {
            EXPR expr = nubInfo.TmpExpr[iexpr];

            DebugUtil.Assert(expr != null);

            if (nubInfo.PostExpr[iexpr] == null)
            {
                return(expr);
            }

            return(AddSideEffects(treeNode, expr, nubInfo.PostExpr[iexpr], false, true));
        }
Exemplo n.º 17
0
 //------------------------------------------------------------
 // FUNCBREC.EnsureNonConstNonLvalue
 //
 /// <summary>
 /// If exprBase is a constant or lvalue,
 /// sequence it with EK_NOOP so it doesn't appear to be either.
 /// </summary>
 /// <param name="tree"></param>
 /// <param name="exprBase"></param>
 /// <returns></returns>
 //------------------------------------------------------------
 private EXPR EnsureNonConstNonLvalue(BASENODE tree, EXPR exprBase)
 {
     if ((exprBase.Flags & EXPRFLAG.LVALUE) == 0 && exprBase.Kind != EXPRKIND.CONSTANT)
     {
         return(exprBase);
     }
     return(NewExprBinop(
                tree,
                EXPRKIND.SEQUENCE,
                exprBase.TypeSym,
                NewExpr(tree, EXPRKIND.NOOP, GetVoidType()),
                exprBase));
 }
Exemplo n.º 18
0
 static internal void DebugNodesAdd(BASENODE node)
 {
     if (node == null)
     {
         return;
     }
     try
     {
         NodeDictionary.Add(node.NodeID, node);
     }
     catch (ArgumentException)
     {
     }
 }
Exemplo n.º 19
0
        //------------------------------------------------------------
        // FUNCBREC.BindNubGetValOrDef
        //
        /// <summary>
        /// Create an expr for exprSrc.GetValueOrDefault()
        /// where exprSrc->type is a NUBSYM.
        /// </summary>
        /// <param name="treeNode"></param>
        /// <param name="srcExpr"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        private EXPR BindNubGetValOrDef(BASENODE treeNode, EXPR srcExpr)
        {
            DebugUtil.Assert(srcExpr != null && srcExpr.TypeSym.IsNUBSYM);

            TYPESYM baseTypeSym = (srcExpr.TypeSym as NUBSYM).BaseTypeSym;

            // If srcExpr is null, just return the appropriate default value.
            if (srcExpr.GetConst() != null)
            {
                return(AddSideEffects(treeNode, NewExprZero(treeNode, baseTypeSym), srcExpr, true, true));
            }

            // For new T?(x), the answer is x.
            if (IsNubCtor(srcExpr))
            {
                DebugUtil.Assert(
                    (srcExpr as EXPRCALL).ArgumentsExpr != null &&
                    (srcExpr as EXPRCALL).ArgumentsExpr.Kind != EXPRKIND.LIST);
                return((srcExpr as EXPRCALL).ArgumentsExpr);
            }

            AGGTYPESYM aggTypeSym = (srcExpr.TypeSym as NUBSYM).GetAggTypeSym();

            if (aggTypeSym == null)
            {
                return(NewError(treeNode, baseTypeSym));
            }
            Compiler.EnsureState(aggTypeSym, AggStateEnum.Prepared);

            METHSYM methSym = EnsureNubGetValOrDef(treeNode);

            if (methSym == null)
            {
                return(NewError(treeNode, baseTypeSym));
            }

            CheckFieldUse(srcExpr, true);

            EXPRCALL resExpr = NewExpr(treeNode, EXPRKIND.CALL, baseTypeSym) as EXPRCALL;

            resExpr.MethodWithInst.Set(methSym, aggTypeSym, BSYMMGR.EmptyTypeArray);
            resExpr.ArgumentsExpr = null;
            resExpr.ObjectExpr    = srcExpr;

            return(resExpr);
        }
Exemplo n.º 20
0
        //------------------------------------------------------------
        // FUNCBREC.BindNubOpRes (1)
        //
        /// <summary>
        /// <para>Combine the condition and value.</para>
        /// <para>(In sscli, warOnNull has the default value false.)</para>
        /// </summary>
        /// <param name="treeNode"></param>
        /// <param name="nubSym"></param>
        /// <param name="dstTypeSym"></param>
        /// <param name="valueExpr"></param>
        /// <param name="nubInfo"></param>
        /// <param name="warnOnNull"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        private EXPR BindNubOpRes(
            BASENODE treeNode,
            NUBSYM nubSym,
            TYPESYM dstTypeSym,
            EXPR valueExpr,
            ref NubInfo nubInfo,
            bool warnOnNull)    // = false
        {
            if (nubInfo.FAlwaysNull() && warnOnNull)
            {
                Compiler.Error(treeNode, CSCERRID.WRN_AlwaysNull, new ErrArg(nubSym));
            }

            return(BindNubOpRes(
                       treeNode,
                       dstTypeSym,
                       valueExpr,
                       NewExprZero(treeNode, dstTypeSym.IsNUBSYM ? dstTypeSym : nubSym),
                       ref nubInfo));
        }
Exemplo n.º 21
0
        //------------------------------------------------------------
        // FUNCBREC.EnsureNubGetValOrDef
        //
        /// <summary>
        /// Make sure the HasValue property of System.Nullable&lt;T&gt; is appropriate (and return it).
        /// </summary>
        /// <param name="treeNode"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        private METHSYM EnsureNubGetValOrDef(BASENODE treeNode)
        {
            METHSYM methSym = Compiler.MainSymbolManager.NullableGetValOrDefMethodSym;

            if (methSym == null)
            {
                AGGSYM nubAggSym = Compiler.GetOptPredefAggErr(PREDEFTYPE.G_OPTIONAL, true);
                if (nubAggSym == null)
                {
                    return(null);
                }
                string name = Compiler.NameManager.GetPredefinedName(PREDEFNAME.GET_VALUE_OR_DEF);

                for (SYM sym = Compiler.MainSymbolManager.LookupAggMember(name, nubAggSym, SYMBMASK.ALL);
                     ;
                     sym = sym.NextSameNameSym)
                {
                    if (sym == null)
                    {
                        Compiler.Error(treeNode, CSCERRID.ERR_MissingPredefinedMember,
                                       new ErrArg(nubAggSym), new ErrArg(name));
                        return(null);
                    }
                    if (sym.IsMETHSYM)
                    {
                        methSym = sym as METHSYM;
                        if (methSym.ParameterTypes.Count == 0 &&
                            methSym.ParameterTypes.Count == 0 &&
                            methSym.ReturnTypeSym.IsTYVARSYM &&
                            !methSym.IsStatic &&
                            methSym.Access == ACCESS.PUBLIC)
                        {
                            break;
                        }
                    }
                }
                Compiler.MainSymbolManager.NullableGetValOrDefMethodSym = methSym;
            }

            return(methSym);
        }
Exemplo n.º 22
0
        //------------------------------------------------------------
        // CLSDREC.CheckFlagsAndSigOfPartialMethod
        //
        /// <summary></summary>
        /// <param name="nodeFlags"></param>
        /// <param name="methodSym"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        internal void CheckFlagsAndSigOfPartialMethod(
            BASENODE treeNode,
            NODEFLAGS nodeFlags,
            METHSYM methodSym)
        {
            const NODEFLAGS forbidden = 0
                                        | NODEFLAGS.MOD_ABSTRACT
                                        | NODEFLAGS.MOD_NEW
                                        | NODEFLAGS.MOD_OVERRIDE
                                        | NODEFLAGS.MOD_PRIVATE
                                        | NODEFLAGS.MOD_PROTECTED
                                        | NODEFLAGS.MOD_INTERNAL
                                        | NODEFLAGS.MOD_PUBLIC
                                        | NODEFLAGS.MOD_SEALED
                                        | NODEFLAGS.MOD_VIRTUAL
                                        | NODEFLAGS.MOD_EXTERN;

            if ((nodeFlags & forbidden) != 0)
            {
                Compiler.Error(treeNode, CSCERRID.ERR_BadModifierForPartialMethod);
            }

            TypeArray paramTypes = methodSym.ParameterTypes;

            if (paramTypes != null && paramTypes.Count > 0)
            {
                for (int i = 0; i < paramTypes.Count; ++i)
                {
                    TYPESYM typeSym = paramTypes[i];
                    if (typeSym.Kind == SYMKIND.PARAMMODSYM &&
                        (typeSym as PARAMMODSYM).IsOut)
                    {
                        Compiler.Error(
                            treeNode,
                            CSCERRID.ERR_PartialMethodHasOutParameter);
                    }
                }
            }
        }
Exemplo n.º 23
0
        //------------------------------------------------------------
        // FUNCBREC.BindNubAddTmps
        //
        /// <summary>
        /// Combines the pre and post expressions of the NubInfo with exprRes.
        /// The pre and post exprs are typically to store values to temps and free the temps.
        /// </summary>
        /// <param name="treeNode"></param>
        /// <param name="resExpr"></param>
        /// <param name="nubInfo"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        private EXPR BindNubAddTmps(BASENODE treeNode, EXPR resExpr, ref NubInfo nubInfo)
        {
            if (nubInfo.PostExpr[1] != null)
            {
                resExpr = NewExprBinop(treeNode, EXPRKIND.SEQREV, resExpr.TypeSym, resExpr, nubInfo.PostExpr[1]);
            }
            if (nubInfo.PostExpr[0] != null)
            {
                resExpr = NewExprBinop(treeNode, EXPRKIND.SEQREV, resExpr.TypeSym, resExpr, nubInfo.PostExpr[0]);
            }

            if (nubInfo.PreExpr[1] != null)
            {
                resExpr = NewExprBinop(treeNode, EXPRKIND.SEQUENCE, resExpr.TypeSym, nubInfo.PreExpr[1], resExpr);
            }
            if (nubInfo.PreExpr[0] != null)
            {
                resExpr = NewExprBinop(treeNode, EXPRKIND.SEQUENCE, resExpr.TypeSym, nubInfo.PreExpr[0], resExpr);
            }

            return(resExpr);
        }
Exemplo n.º 24
0
        //------------------------------------------------------------
        // FUNCBREC.BindUnaryOperator
        //
        // EXPR * BindStdUnaOp(BASENODE * tree, OPERATOR op, EXPR * arg);
        // EXPR * BindIntUnaOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg);
        // EXPR * BindRealUnaOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg);
        // EXPR * BindDecUnaOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg);
        // EXPR * BindBoolUnaOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg);
        // EXPR * BindEnumUnaOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg);
        //------------------------------------------------------------
        internal EXPR BindUnaryOperator(
            BindUnaOpEnum op,
            BASENODE tree,
            EXPRKIND ek,
            EXPRFLAG flags,
            EXPR arg)
        {
            switch (op)
            {
            case BindUnaOpEnum.Integer:
                // Handles standard unary integer based operators.
                // EXPR * FUNCBREC::BindIntUnaOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg)
                DebugUtil.Assert(arg.TypeSym.IsPredefined());
                return(BindIntOp(tree, ek, flags, arg, null, arg.TypeSym.GetPredefType()));

            case BindUnaOpEnum.Real:
                // Handles standard unary floating point (float, double) based operators.
                // EXPR * FUNCBREC::BindRealUnaOp(BASENODE * tree, EXPRKIND ek, uint flags, EXPR * arg)
                DebugUtil.Assert(arg.TypeSym.IsPredefined());
                return(BindFloatOp(tree, ek, flags, arg, null));

            case BindUnaOpEnum.Decimal:
                return(BindDecUnaOp(tree, ek, flags, arg));

            case BindUnaOpEnum.Bool:
                return(BindBoolUnaOp(tree, ek, flags, arg));

                break;

            case BindUnaOpEnum.Enum:
                return(BindEnumUnaOp(tree, ek, flags, arg));

            default:
                DebugUtil.Assert(false, "FUNCBREC.BindUnaryOperator");
                break;
            }
            return(null);
        }
Exemplo n.º 25
0
        //------------------------------------------------------------
        // FUNCBREC.BindQMark
        //
        /// <summary>
        /// <para>Constructs an expr for "exprCond ? exprLeft : exprRight". If fInvert is true, reverses
        /// exprLeft and exprRight.</para>
        /// <para>(In sscli, fInvert has the default value false.)</para>
        /// </summary>
        /// <remarks>
        /// REVIEW ShonK: Optimize BindQmark when the condition is a constant (with possible side effects).
        /// </remarks>
        /// <param name="tree"></param>
        /// <param name="condExpr"></param>
        /// <param name="leftExpr"></param>
        /// <param name="rightExpr"></param>
        /// <param name="fInvert"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        private EXPR BindQMark(
            BASENODE tree,
            EXPR condExpr,
            EXPR leftExpr,
            EXPR rightExpr,
            bool fInvert)   // =false
        {
            DebugUtil.Assert(condExpr.TypeSym.IsPredefType(PREDEFTYPE.BOOL));
            DebugUtil.Assert(leftExpr.TypeSym == rightExpr.TypeSym);

            EXPR colonExpr;

            if (fInvert)
            {
                colonExpr = NewExprBinop(tree, EXPRKIND.BINOP, null, rightExpr, leftExpr);
            }
            else
            {
                colonExpr = NewExprBinop(tree, EXPRKIND.BINOP, null, leftExpr, rightExpr);
            }

            return(NewExprBinop(tree, EXPRKIND.QMARK, leftExpr.TypeSym, condExpr, colonExpr));
        }
Exemplo n.º 26
0
        //------------------------------------------------------------
        // FUNCBREC.BindNubOpRes (2)
        //
        /// <summary>
        /// Combine the condition and value.
        /// </summary>
        /// <param name="treeNode"></param>
        /// <param name="dstTypeSym"></param>
        /// <param name="valueExpr"></param>
        /// <param name="nullExpr"></param>
        /// <param name="nubInfo"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        private EXPR BindNubOpRes(
            BASENODE treeNode,
            TYPESYM dstTypeSym,
            EXPR valueExpr,
            EXPR nullExpr,
            ref NubInfo nubInfo)
        {
            EXPR resExpr;

            nullExpr  = MustConvert(nullExpr, dstTypeSym, 0);
            valueExpr = MustConvert(valueExpr, dstTypeSym, 0);

            if (nubInfo.FAlwaysNonNull())
            {
                // Don't need nullExpr and there aren't any temps.
                resExpr = valueExpr;
            }
            else if (nubInfo.FAlwaysNull())
            {
                // Don't need valueExpr but do need side effects.
                resExpr = BindNubAddTmps(treeNode, nullExpr, ref nubInfo);
            }
            else
            {
                DebugUtil.Assert(nubInfo.CombinedConditionExpr != null);
                resExpr = BindQMark(
                    treeNode,
                    nubInfo.CombinedConditionExpr,
                    MustConvert(valueExpr, dstTypeSym, 0),
                    nullExpr,
                    false);
                resExpr = BindNubAddTmps(treeNode, resExpr, ref nubInfo);
            }

            return(resExpr);
        }
Exemplo n.º 27
0
        //------------------------------------------------------------
        // MetaDataHelper.GetExplicitImplName
        //
        /// <summary>
        /// Get a synthesized name for explicit interface implementations.
        /// The name we use is: "InterfaceName.MethodName", where InterfaceName is the fully qualified name
        /// of the interface containing the implemented method.
        /// This name has a '.' in it, so it can't conflict with any "real" name or be confused with one.
        /// </summary>
        /// <remarks>
        /// Returns true if the buffer had enough space for the name.
        /// If not enough space, then adds as much of name as possible to buffer.
        /// Always NULL terminates buffer.
        /// </remarks>
        /// <param name="sym"></param>
        /// <param name="strBuilder"></param>
        //------------------------------------------------------------
        public void GetExplicitImplName(SYM sym, StringBuilder strBuilder)
        {
            DebugUtil.Assert(sym.IsEVENTSYM || sym.IsMETHPROPSYM);

            SymWithType swtImpl   = new SymWithType();
            ERRORSYM    errSym    = null;
            string      implName  = null;
            string      aliasName = null;

            switch (sym.Kind)
            {
            case SYMKIND.EVENTSYM:
                EVENTSYM eventSym = sym as EVENTSYM;
                DebugUtil.Assert(eventSym.IsExpImpl);
                swtImpl = eventSym.SlotEventWithType;
                errSym  = eventSym.ExpImplErrorSym;
                break;

            case SYMKIND.METHSYM:
            case SYMKIND.PROPSYM:
            {
                METHPROPSYM mpSym = sym as METHPROPSYM;
                DebugUtil.Assert(mpSym.IsExplicitImplementation);
                swtImpl = mpSym.SlotSymWithType;
                errSym  = mpSym.ExpImplErrorSym;
                BASENODE nameNode = null;

                if (sym.IsMETHSYM &&
                    (sym as METHSYM).ParseTreeNode != null &&
                    (sym as METHSYM).ParseTreeNode.Kind == NODEKIND.METHOD)
                {
                    nameNode = ((sym as METHSYM).ParseTreeNode as METHODNODE).NameNode;
                }
                else if (
                    sym.IsPROPSYM &&
                    (sym as PROPSYM).ParseTreeNode != null &&
                    (sym as PROPSYM).ParseTreeNode.Kind == NODEKIND.PROPERTY)
                {
                    nameNode = ((sym as PROPSYM).ParseTreeNode as PROPERTYNODE).NameNode;
                }

                while (nameNode != null && nameNode.Kind == NODEKIND.DOT)
                {
                    nameNode = nameNode.AsDOT.Operand1;
                }

                if (nameNode != null && nameNode.Kind == NODEKIND.ALIASNAME)
                {
                    aliasName = nameNode.AsANYNAME.Name;
                }
                if (!sym.IsPROPSYM || !(sym as PROPSYM).IsIndexer)
                {
                    break;
                }

                implName = (swtImpl != null ? (swtImpl.Sym as PROPSYM).GetRealName() : "Item");
                // fish out any user specified alias
                break;
            }

            default:
                // gcc -Wall (all warnings enabled) complains if all cases
                // aren't handled, so we explicitly handle default and assert
                DebugUtil.Assert(false);
                break;
            }

            DebugUtil.Assert(swtImpl != null || errSym != null);

            if (aliasName != null)
            {
                strBuilder.Append(aliasName);
                strBuilder.Append("::");
            }

            if (swtImpl != null)
            {
                GetExplicitImplTypeName(swtImpl.AggTypeSym, strBuilder);
                if (implName == null)
                {
                    implName = swtImpl.Sym.Name;
                }
            }
            else
            {
                GetExplicitImplTypeName(errSym, strBuilder);
            }

            if (implName != null)
            {
                // Add dot seperator.
                strBuilder.Append('.');
                strBuilder.Append(implName);
            }
        }
Exemplo n.º 28
0
        //------------------------------------------------------------
        // FUNCBREC.BindNubConstBool
        //
        /// <summary>
        /// Return an expr for "new bool?(fT)".
        /// </summary>
        /// <param name="tree"></param>
        /// <param name="fT"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        private EXPR BindNubConstBool(BASENODE tree, bool fT)
        {
            EXPR expr = NewExprConstant(tree, GetRequiredPredefinedType(PREDEFTYPE.BOOL), new ConstValInit(fT));

            return(BindNubNew(tree, expr));
        }
Exemplo n.º 29
0
        //------------------------------------------------------------
        // FUNCBREC.BindNubCondValBin
        //
        /// <summary>
        /// <para>Fill in the NubInfo for a unary or binary operator lifting.</para>
        /// <para>(In sscli, liftFlags has default value LiftFlags::LiftBoth.)</para>
        /// </summary>
        /// <param name="treeNode"></param>
        /// <param name="expr1"></param>
        /// <param name="expr2"></param>
        /// <param name="nubInfo"></param>
        /// <param name="liftFlags"></param>
        //------------------------------------------------------------
        private void BindNubCondValBin(
            BASENODE treeNode,
            EXPR expr1,
            EXPR expr2,
            ref NubInfo nubInfo,
            LiftFlagsEnum liftFlags)    // = LiftFlags::LiftBoth
        {
            DebugUtil.Assert((liftFlags & (LiftFlagsEnum.Lift1 | LiftFlagsEnum.Lift2)) != 0);
            DebugUtil.Assert(expr1 != null);
            DebugUtil.Assert(expr2 != null || (liftFlags & LiftFlagsEnum.Lift1) != 0);

            nubInfo.Init();

            bool[] rgfLift = { false, false };
            rgfLift[0] = ((liftFlags & LiftFlagsEnum.Lift1) != 0);
            rgfLift[1] = expr2 != null && ((liftFlags & LiftFlagsEnum.Lift2) != 0);

            EXPR[] rgexpr = { null, null };
            rgexpr[0] = rgfLift[0] ? StripNubCtor(expr1) : expr1;
            rgexpr[1] = rgfLift[1] ? StripNubCtor(expr2) : expr2;

            if ((!rgfLift[0] || !rgexpr[0].TypeSym.IsNUBSYM) && (!rgfLift[1] || !rgexpr[1].TypeSym.IsNUBSYM))
            {
                // All lifted params can't be null so we don't need temps.
                nubInfo.ValueExpr[0]    = rgexpr[0];
                nubInfo.ValueExpr[1]    = rgexpr[1];
                nubInfo.IsActive        = true;
                nubInfo.IsAlwaysNonNull = true;
                return;
            }

            // Optimization: if they are the same local then we only need one temp.
            if (rgexpr[1] != null &&
                rgexpr[0].Kind == EXPRKIND.LOCAL &&
                rgexpr[1].Kind == EXPRKIND.LOCAL &&
                (rgexpr[0] as EXPRLOCAL).LocVarSym == (rgexpr[1] as EXPRLOCAL).LocVarSym &&
                rgfLift[0] == rgfLift[1])
            {
                BindNubSave(rgexpr[0], ref nubInfo, 0, rgfLift[0]);
                DebugUtil.Assert(nubInfo.TmpExpr[0].Kind == EXPRKIND.LDTMP);
                nubInfo.TmpExpr[1] = nubInfo.TmpExpr[0];
                nubInfo.IsSameTemp = true;
            }
            else
            {
                BindNubSave(rgexpr[0], ref nubInfo, 0, rgfLift[0]);
                if (rgexpr[1] != null)
                {
                    BindNubSave(rgexpr[1], ref nubInfo, 1, rgfLift[1]);
                }
            }

            for (int iexpr = 0; iexpr < 2 && rgexpr[iexpr] != null; iexpr++)
            {
                if (!rgfLift[iexpr] || !nubInfo.TmpExpr[iexpr].TypeSym.IsNUBSYM)
                {
                    nubInfo.ValueExpr[iexpr] = nubInfo.TmpExpr[iexpr];
                    continue;
                }
                nubInfo.ValueExpr[iexpr] = BindNubGetValOrDef(treeNode, nubInfo.TmpExpr[iexpr]);
                DebugUtil.Assert(!nubInfo.ValueExpr[iexpr].TypeSym.IsNUBSYM);
                if (nubInfo.FConst(iexpr))
                {
                    nubInfo.IsNull[iexpr] = nubInfo.IsAlwaysNull = true;
                }
                else if (nubInfo.IsSameTemp && iexpr != 0)
                {
                    nubInfo.ConditionExpr[iexpr] = nubInfo.ConditionExpr[0];
                }
                else
                {
                    nubInfo.ConditionExpr[iexpr] = BindNubHasValue(treeNode, nubInfo.TmpExpr[iexpr], true);
                }
            }

            if (!nubInfo.IsAlwaysNull)
            {
                if (nubInfo.ConditionExpr[0] == null)
                {
                    nubInfo.CombinedConditionExpr = nubInfo.ConditionExpr[1];
                }
                else if (nubInfo.ConditionExpr[1] == null || nubInfo.IsSameTemp)
                {
                    nubInfo.CombinedConditionExpr = nubInfo.ConditionExpr[0];
                }
                else
                {
                    nubInfo.CombinedConditionExpr = NewExprBinop(
                        treeNode,
                        EXPRKIND.BITAND,
                        GetRequiredPredefinedType(PREDEFTYPE.BOOL),
                        nubInfo.ConditionExpr[0],
                        nubInfo.ConditionExpr[1]);
                }
            }
            else
            {
                // One of the operands is null so the result will always be null and we
                // don't need the temps.
                if (nubInfo.PreExpr[0] != null && nubInfo.PreExpr[0].Kind == EXPRKIND.STTMP)
                {
                    nubInfo.PreExpr[0] = (nubInfo.PreExpr[0] as EXPRSTTMP).SourceExpr;
                }
                if (nubInfo.PreExpr[1] != null && nubInfo.PreExpr[1].Kind == EXPRKIND.STTMP)
                {
                    nubInfo.PreExpr[1] = (nubInfo.PreExpr[1] as EXPRSTTMP).SourceExpr;
                }
                nubInfo.PostExpr[0] = null;
                nubInfo.PostExpr[1] = null;
            }

            nubInfo.IsActive = true;
            DebugUtil.Assert(nubInfo.CombinedConditionExpr != null || nubInfo.IsAlwaysNull);
        }
Exemplo n.º 30
0
        //------------------------------------------------------------
        // FUNCBREC.BindNubHasValue
        //
        /// <summary>
        /// <para>Create an expr for exprSrc.HasValue where exprSrc->type is a NUBSYM.</para>
        /// <para>If fCheckTrue is false, invert the result.</para>
        /// <para>(In sscli, checkTrue has the default value true.)</para>
        /// </summary>
        /// <param name="treeNode"></param>
        /// <param name="srcExpr"></param>
        /// <param name="checkTrue"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        private EXPR BindNubHasValue(
            BASENODE treeNode,
            EXPR srcExpr,
            bool checkTrue) // = true
        {
            DebugUtil.Assert(srcExpr != null && srcExpr.TypeSym.IsNUBSYM);

            TYPESYM boolTypeSym = GetRequiredPredefinedType(PREDEFTYPE.BOOL);

            // When srcExpr is a null, the result is false
            if (srcExpr.GetConst() != null)
            {
                return(AddSideEffects(
                           treeNode,
                           NewExprConstant(treeNode, boolTypeSym, new ConstValInit(!checkTrue)),
                           srcExpr,
                           true,
                           true));
            }

            // For new T?(x), the answer is true.
            if (IsNubCtor(srcExpr))
            {
                return(AddSideEffects(
                           treeNode,
                           NewExprConstant(treeNode, boolTypeSym, new ConstValInit(checkTrue)),
                           StripNubCtor(srcExpr),
                           true,
                           true));
            }

            AGGTYPESYM aggTypeSym = (srcExpr.TypeSym as NUBSYM).GetAggTypeSym();

            if (aggTypeSym == null)
            {
                return(NewError(treeNode, boolTypeSym));
            }
            Compiler.EnsureState(aggTypeSym, AggStateEnum.Prepared);

            PROPSYM propSym = EnsureNubHasValue(treeNode);

            if (propSym == null)
            {
                return(NewError(treeNode, boolTypeSym));
            }

            CheckFieldUse(srcExpr, true);

            EXPRPROP resExpr = NewExpr(treeNode, EXPRKIND.PROP, boolTypeSym) as EXPRPROP;

            resExpr.SlotPropWithType.Set(propSym, aggTypeSym);
            resExpr.GetMethodWithType.Set(propSym.GetMethodSym, aggTypeSym);
            resExpr.ArgumentsExpr = null;
            resExpr.ObjectExpr    = srcExpr;

            if (checkTrue)
            {
                return(resExpr);
            }

            return(NewExprBinop(treeNode, EXPRKIND.LOGNOT, resExpr.TypeSym, resExpr, null));
        }