Beispiel #1
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);
        }
Beispiel #2
0
        //------------------------------------------------------------
        // MetaDataHelper.AddTypeModifiers
        //
        /// <summary>
        /// appends array and ptr modifiers
        /// </summary>
        /// <param name="typeSym"></param>
        /// <param name="strBuilder"></param>
        //------------------------------------------------------------
        protected void AddTypeModifiers(TYPESYM typeSym, StringBuilder strBuilder)
        {
            switch (typeSym.Kind)
            {
            case SYMKIND.AGGTYPESYM:
            case SYMKIND.TYVARSYM:
            case SYMKIND.ERRORSYM:
            case SYMKIND.NUBSYM:
                break;

            case SYMKIND.ARRAYSYM:
                // NOTE: In C# a 2-dim array of 1-dim array of int is int[,][].
                // This produces int[][,] as metadata requires.
                AddTypeModifiers((typeSym as ARRAYSYM).ElementTypeSym, strBuilder);
                strBuilder.Append('[');
                for (int i = 1; i < (typeSym as ARRAYSYM).Rank; ++i)
                {
                    strBuilder.Append(',');
                }
                strBuilder.Append(']');
                break;

            case SYMKIND.PTRSYM:
                AddTypeModifiers((typeSym as PTRSYM).BaseTypeSym, strBuilder);
                strBuilder.Append('*');
                break;

            default:
                DebugUtil.Assert(false, "Unknown symbol typeSym");
                break;
            }
        }
Beispiel #3
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);
        }
        //------------------------------------------------------------
        // 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;
            }
        }
        //------------------------------------------------------------
        // CLSDREC.CreateBackField
        //
        /// <summary></summary>
        /// <param name="aggSym"></param>
        /// <param name="propName"></param>
        //------------------------------------------------------------
        private MEMBVARSYM CreateBackField(
            PROPERTYNODE propNode,
            string propName,
            TYPESYM propTypeSym,
            AGGSYM aggSym,
            AGGDECLSYM aggDeclSym)
        {
            DebugUtil.Assert(aggSym.IsClass || aggSym.IsStruct);
            string backFieldName = GenerateBackFieldName(propName);

            NODEFLAGS propFlags = propNode.Flags;

            MEMBVARSYM backFieldSym = Compiler.MainSymbolManager.CreateMembVar(
                backFieldName,
                aggSym,
                aggDeclSym);

            backFieldSym.TypeSym       = propTypeSym;
            backFieldSym.ParseTreeNode = null;
            backFieldSym.IsAssigned    = true;

            NODEFLAGS allowableFlags =
                aggSym.AllowableMemberAccess() |
                NODEFLAGS.MOD_UNSAFE |
                NODEFLAGS.MOD_NEW |
                NODEFLAGS.MOD_STATIC;

            backFieldSym.IsUnsafe = (aggDeclSym.IsUnsafe || (propFlags & NODEFLAGS.MOD_UNSAFE) != 0);

            if ((propFlags & NODEFLAGS.MOD_ABSTRACT) != 0)
            {
                DebugUtil.Assert((allowableFlags & NODEFLAGS.MOD_ABSTRACT) == 0);
                Compiler.ErrorRef(null, CSCERRID.ERR_AbstractField, new ErrArgRef(backFieldSym));
                //flags &= ~NODEFLAGS.MOD_ABSTRACT;
            }

            backFieldSym.Access = ACCESS.PRIVATE;   // GetAccessFromFlags(aggSym, allowableFlags, flags);

            if ((propFlags & NODEFLAGS.MOD_STATIC) != 0)
            {
                backFieldSym.IsStatic = true;
            }

            CheckForProtectedInSealed(backFieldSym);

            // Check that the field type is as accessible as the field itself.
            CheckConstituentVisibility(backFieldSym, propTypeSym, CSCERRID.ERR_BadVisFieldType);

            return(backFieldSym);
        }
        //------------------------------------------------------------
        // FUNCBREC.BindImplicitlyTypedArrayInit
        //
        /// <summary></summary>
        /// <param name="treeNode"></param>
        /// <param name="arrayTypeSym"></param>
        /// <param name="argListExpr"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        internal EXPR BindImplicitlyTypedArrayInit(
            UNOPNODE treeNode,
            ref TYPESYM arrayTypeSym)
        {
            EXPRARRINIT arrayInitExpr = NewExpr(
                treeNode,
                EXPRKIND.ARRINIT,
                null) as EXPRARRINIT;

            arrayInitExpr.Flags |= EXPRFLAG.CANTBENULL;

            TYPESYM elementTypeSym = null;

            arrayInitExpr.DimSizes = new List <int>();
            arrayInitExpr.DimSizes.Add(-1);

            //bool isConstant =
            //    elementTypeSym.IsSimpleType() &&
            //    BSYMMGR.GetAttrArgSize(elementTypeSym.GetPredefType()) > 0;
            int  nonConstCount  = 0;
            int  constCount     = 0;
            bool hasSideEffects = false;

            BindImplicitlyTypedArrayInitCore(
                treeNode,
                ref elementTypeSym,
                arrayInitExpr.DimSizes,
                0,
                ref arrayInitExpr.ArgumentsExpr);

            arrayTypeSym = Compiler.MainSymbolManager.GetArray(
                elementTypeSym,
                1,
                null);
            arrayInitExpr.TypeSym = arrayTypeSym;

            BindImplicitlyTypedArrayInitConvert(
                elementTypeSym,
                arrayInitExpr.DimSizes,
                0,
                ref arrayInitExpr.ArgumentsExpr,
                ref nonConstCount,
                ref constCount,
                ref hasSideEffects);

            return(arrayInitExpr);
        }
Beispiel #7
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);
        }
Beispiel #8
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));
        }
Beispiel #9
0
        //------------------------------------------------------------
        // FUNCBREC.BindTypeOf
        //
        /// <summary>
        /// <para>Defined in FuncBindUtil.cs</para>
        /// </summary>
        /// <param name="treeNode"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        private EXPRTYPEOF BindTypeOf(TYPESYM typeSym)
        {
            DebugUtil.Assert(typeSym != null);
            if (typeSym.IsERRORSYM)
            {
                goto LERROR;
            }

            if (typeSym == GetVoidType())
            {
                typeSym = this.GetRequiredPredefinedType(PREDEFTYPE.SYSTEMVOID);
            }

            EXPRTYPEOF typeofExpr = null;

            typeofExpr = NewExpr(
                treeNode,
                EXPRKIND.TYPEOF,
                this.GetRequiredPredefinedType(PREDEFTYPE.TYPE)) as EXPRTYPEOF;
            typeofExpr.MethodSym     = CreateGetTypeFromHandleMethodSym(null);
            typeofExpr.SourceTypeSym = typeSym;
#if false
            if (operandNode.Kind == NODEKIND.OPENTYPE)
            {
                DebugUtil.Assert(
                    typeSym.IsAGGTYPESYM &&
                    (typeSym as AGGTYPESYM).AllTypeArguments.Count > 0 &&
                    (typeSym as AGGTYPESYM).AllTypeArguments[(typeSym as AGGTYPESYM).AllTypeArguments.Count - 1].IsUNITSYM);
                rval.Flags |= EXPRFLAG.OPENTYPE;
            }
#endif

            typeofExpr.Flags |= EXPRFLAG.CANTBENULL;
            return(typeofExpr);

LERROR:
            //return NewError(treeNode, this.GetRequiredPredefinedType(PREDEFTYPE.TYPE));
            return(null);
        }
Beispiel #10
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);
                    }
                }
            }
        }
Beispiel #11
0
        //------------------------------------------------------------
        // FUNCBREC.CreateNewLocVarSym
        //
        /// <summary>Increments the following values:
        /// FUNCBREC.localCount,
        /// FUNCBREC.unreferencedVarCount and
        /// FUNCBREC.uninitedVarCount.
        /// And sets LOCVARSYM.LocSlotInfo.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="typeSym"></param>
        /// <param name="parentSym"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        internal LOCVARSYM CreateNewLocVarSym(
            string name,
            TYPESYM typeSym,
            PARENTSYM parentSym)
        {
            SYM sym = Compiler.LocalSymbolManager.LookupLocalSym(
                name,
                parentSym,
                SYMBMASK.LOCVARSYM);

            if (sym != null)
            {
                return(sym as LOCVARSYM);
            }

            LOCVARSYM locSym = Compiler.LocalSymbolManager.CreateLocalSym(
                SYMKIND.LOCVARSYM,
                name,
                parentSym) as LOCVARSYM;

            locSym.TypeSym = typeSym;

            StoreInCache(null, name, locSym, null, true);

            ++this.localCount;
            if (this.localCount > 0xffff)
            {
                Compiler.Error(treeNode, CSCERRID.ERR_TooManyLocals);
            }
            ++this.unreferencedVarCount;

            locSym.LocSlotInfo.SetJbitDefAssg(this.uninitedVarCount + 1);
            int cbit = FlowChecker.GetCbit(Compiler, locSym.TypeSym);

            this.uninitedVarCount += cbit;

            return(locSym);
        }
Beispiel #12
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);
        }
Beispiel #13
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));
        }
Beispiel #14
0
        //------------------------------------------------------------
        // FUNCBREC.BindNubConversion
        //
        // Called by bindImplicitConversion when the destination type is Nullable&lt;T&gt;. The following
        // conversions are handled by this method:
        //
        // * For S in { object, ValueType, interfaces implemented by underlying type} there is an explicit
        // unboxing conversion S =&gt; T?
        // * System.Enum =&gt; T? there is an unboxing conversion if T is an enum type
        // * null =&gt; T? implemented as default(T?)
        //
        // * Implicit T?* =&gt; T?+ implemented by either wrapping or calling GetValueOrDefault the
        // appropriate number of times.
        // * If imp/exp S =&gt; T then imp/exp S =&gt; T?+ implemented by converting to T then wrapping the
        // appropriate number of times.
        // * If imp/exp S =&gt; T then imp/exp S?+ =&gt; T?+ implemented by calling GetValueOrDefault (m-1) times
        // then calling HasValue, producing a null if it returns false, otherwise calling Value,
        // converting to T then wrapping the appropriate number of times.
        //
        // The 3 rules above can be summarized with the following recursive rules:
        //
        // * If imp/exp S =&gt; T? then imp/exp S? =&gt; T? implemented as
        // qs.HasValue ? (T?)(qs.Value) : default(T?)
        // * If imp/exp S =&gt; T then imp/exp S =&gt; T? implemented as new T?((T)s)
        //
        // This method also handles calling bindUserDefinedConverion. This method does NOT handle
        // the following conversions:
        //
        // * Implicit boxing conversion from S? to { object, ValueType, Enum, ifaces implemented by S }. (Handled by bindImplicitConversion.)
        // * If imp/exp S =&gt; T then explicit S?+ =&gt; T implemented by calling Value the appropriate number
        // of times. (Handled by bindExplicitConversion.)
        //
        // The recursive equivalent is:
        //
        // * If imp/exp S =&gt; T and T is not nullable then explicit S? =&gt; T implemented as qs.Value
        //
        // Some nullable conversion are NOT standard conversions. In particular, if S =&gt; T is implicit
        // then S? =&gt; T is not standard. Similarly if S =&gt; T is not implicit then S =&gt; T? is not standard.
        //
        /// <summary></summary>
        /// <param name="treeNode"></param>
        /// <param name="srcExpr"></param>
        /// <param name="srcTypeSym"></param>
        /// <param name="dstNubSym"></param>
        /// <param name="dstExpr"></param>
        /// <param name="flags"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        private bool BindNubConversion(
            BASENODE treeNode,
            EXPR srcExpr,
            TYPESYM srcTypeSym,
            NUBSYM dstNubSym,
            ref EXPR dstExpr,
            ConvertTypeEnum flags)
        {
            // This code assumes that STANDARD and ISEXPLICIT are never both set.
            // bindUserDefinedConversion should ensure this!
            DebugUtil.Assert((~flags & (ConvertTypeEnum.STANDARD | ConvertTypeEnum.ISEXPLICIT)) != 0);

            DebugUtil.Assert(srcExpr == null || srcExpr.TypeSym == srcTypeSym);
            DebugUtil.Assert(dstExpr == null || srcExpr != null);

            DebugUtil.Assert(srcTypeSym != dstNubSym);
            // bindImplicitConversion should have taken care of this already.

            AGGTYPESYM dstAggTypeSym = dstNubSym.GetAggTypeSym();

            if (dstAggTypeSym == null)
            {
                return(false);
            }

            // Check for the unboxing conversion. This takes precedence over the wrapping conversions.
            if (Compiler.IsBaseType(dstNubSym.BaseTypeSym, srcTypeSym) && !FWrappingConv(srcTypeSym, dstNubSym))
            {
                // These should be different! Fix the caller if srcTypeSym is an AGGTYPESYM of Nullable.
                DebugUtil.Assert(dstAggTypeSym != srcTypeSym);

                // srcTypeSym is a base type of the destination nullable type so there is an explicit
                // unboxing conversion.
                if ((flags & ConvertTypeEnum.ISEXPLICIT) == 0)
                {
                    return(false);
                }
                return(BindSimpleCast(treeNode, srcExpr, dstNubSym, ref dstExpr, EXPRFLAG.UNBOX));
            }

            int     dstNubStripCount;
            int     srcNubStripCount;
            TYPESYM dstBaseTypeSym = dstNubSym.StripNubs(out dstNubStripCount);
            TYPESYM srcBaseTypeSym = srcTypeSym.StripNubs(out srcNubStripCount);

            bindNubConversion_Convert fnConvert;
            EXPR expr = null;   // temp

            if ((flags & ConvertTypeEnum.ISEXPLICIT) != 0)
            {
                fnConvert = new bindNubConversion_Convert(BindExplicitConversion);
            }
            else
            {
                fnConvert = new bindNubConversion_Convert(BindImplicitConversion);
            }

            //bool (FUNCBREC::*pfn)(BASENODE *, EXPR *, TYPESYM *, TYPESYM *, EXPR **, uint) =
            //    (flags & ISEXPLICIT) ? &FUNCBREC::bindExplicitConversion : &FUNCBREC::bindImplicitConversion;

            if (srcNubStripCount == 0)
            {
                DebugUtil.Assert(srcTypeSym == srcBaseTypeSym);

                // The null type can be implicitly converted to T? as the default value.
                if (srcTypeSym.IsNULLSYM)
                {
                    dstExpr = AddSideEffects(treeNode, NewExprZero(treeNode, dstNubSym), srcExpr, true, true);
                    return(true);
                }

                EXPR tempExpr = srcExpr;

                // If there is an implicit/explicit S => T then there is an implicit/explicit S => T?
                if (srcTypeSym == dstBaseTypeSym ||
                    fnConvert(
                        treeNode,
                        srcExpr,
                        srcTypeSym,
                        dstBaseTypeSym,
                        ref tempExpr,
                        flags | ConvertTypeEnum.NOUDC))
                {
                    // srcTypeSym is not nullable so just wrap the required number of times.
                    for (int i = 0; i < dstNubStripCount; i++)
                    {
                        tempExpr = BindNubNew(treeNode, tempExpr);
                    }
                    DebugUtil.Assert(tempExpr.TypeSym == dstNubSym);
                    dstExpr = tempExpr;
                    return(true);
                }

                // No builtin conversion. Maybe there is a user defined conversion....
                return(
                    (flags & ConvertTypeEnum.NOUDC) == 0 &&
                    BindUserDefinedConversion(
                        treeNode,
                        srcExpr,
                        srcTypeSym,
                        dstNubSym,
                        ref dstExpr,
                        (flags & ConvertTypeEnum.ISEXPLICIT) == 0));
            }

            // Both are Nullable so there is only a conversion if there is a conversion between the base types.
            // That is, if there is an implicit/explicit S => T then there is an implicit/explicit S?+ => T?+.
            if (srcBaseTypeSym != dstBaseTypeSym &&
                !fnConvert(treeNode, null, srcBaseTypeSym, dstBaseTypeSym, ref expr, flags | ConvertTypeEnum.NOUDC))
            {
                // No builtin conversion. Maybe there is a user defined conversion....
                return(
                    (flags & ConvertTypeEnum.NOUDC) == 0 &&
                    BindUserDefinedConversion(
                        treeNode,
                        srcExpr,
                        srcTypeSym,
                        dstNubSym,
                        ref dstExpr,
                        (flags & ConvertTypeEnum.ISEXPLICIT) == 0));
            }

            // We need to go all the way down to the base types, do the conversion, then come all the way back up.
            EXPR    valExpr;
            NubInfo nubInfo = new NubInfo();

            BindNubCondValBin(
                treeNode,
                srcExpr,
                null,
                ref nubInfo,
                LiftFlagsEnum.LiftBoth);
            valExpr = nubInfo.Val(0);

            DebugUtil.Assert(valExpr.TypeSym == srcBaseTypeSym);

            if (!fnConvert(
                    treeNode,
                    valExpr,
                    valExpr.TypeSym,
                    dstBaseTypeSym,
                    ref valExpr,
                    flags | ConvertTypeEnum.NOUDC))
            {
                DebugUtil.Assert(false, "bind(Im|Ex)plicitConversion failed unexpectedly");
                return(false);
            }

            for (int i = 0; i < dstNubStripCount; i++)
            {
                valExpr = BindNubNew(treeNode, valExpr);
            }
            DebugUtil.Assert(valExpr.TypeSym == dstNubSym);

            dstExpr = BindNubOpRes(treeNode, dstNubSym, dstNubSym, valExpr, ref nubInfo, false);

            return(true);
        }
Beispiel #15
0
        //------------------------------------------------------------
        // FUNCBREC.BindCollectionInitializer
        //
        /// <summary></summary>
        /// <param name="newNode"></param>
        /// <param name="typeSym"></param>
        /// <param name="locVarSym"></param>
        /// <param name="objectExpr"></param>
        /// <param name="builder"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        internal EXPR BindCollectionInitializer(
            NEWNODE newNode,
            BASENODE elementsNode,
            TYPESYM typeSym,
            LOCVARSYM locVarSym,
            EXPR leftExpr,
            EXPR rightExpr,
            StatementListBuilder builder)
        {
            DebugUtil.Assert(newNode != null && typeSym != null && builder != null);
            DebugUtil.Assert(locVarSym != null || leftExpr != null || rightExpr != null);

            string addMethName = Compiler.NameManager.GetPredefinedName(PREDEFNAME.ADD);

            //--------------------------------------------------------
            // typeSym should implement IEnumerable.
            //--------------------------------------------------------
            AGGTYPESYM enumerableSym = HasIEnumerable(typeSym);

            if (enumerableSym == null)
            {
                Compiler.Error(
                    newNode.TypeNode,
                    CSCERRID.ERR_CollectInitRequiresIEnumerable,
                    new ErrArg(typeSym));
                return(rightExpr);
            }

            TYPESYM   paramTypeSym = null;
            TypeArray typeArgs     = enumerableSym.TypeArguments;

            if (typeArgs != null && typeArgs.Count > 0)
            {
                DebugUtil.Assert(typeArgs.Count == 1);
                paramTypeSym = typeArgs[0];
            }
            else
            {
                paramTypeSym
                    = Compiler.GetReqPredefAgg(PREDEFTYPE.OBJECT, true).GetThisType();
                if (typeArgs == null)
                {
                    typeArgs = new TypeArray();
                }
                typeArgs.Add(paramTypeSym);
                typeArgs = Compiler.MainSymbolManager.AllocParams(typeArgs);
            }

            BindFlagsEnum bindFlags   = BindFlagsEnum.RValueRequired;
            string        localFormat = "<{0}><{1}>__local";

            //--------------------------------------------------------
            // Bind the local variable.
            //--------------------------------------------------------
            if (leftExpr == null)
            {
                if (locVarSym == null)
                {
                    string locName
                        = String.Format(localFormat, typeSym.Name, (this.localCount)++);

                    locVarSym = Compiler.LocalSymbolManager.CreateLocalSym(
                        SYMKIND.LOCVARSYM,
                        locName,
                        this.currentScopeSym) as LOCVARSYM;
                    locVarSym.TypeSym             = typeSym;
                    locVarSym.LocSlotInfo.HasInit = true;
                    locVarSym.DeclTreeNode        = newNode;

                    StoreInCache(newNode, locName, locVarSym, null, true);
                }

                leftExpr = BindToLocal(
                    newNode,
                    locVarSym,
                    bindFlags | BindFlagsEnum.MemberSet);
            }

            //--------------------------------------------------------
            // If objectExpr is not null, assign it to the local variable.
            //--------------------------------------------------------
            if (rightExpr != null)
            {
                EXPR assignLocExpr = BindAssignment(
                    newNode,
                    leftExpr,
                    rightExpr,
                    false);

                builder.Add(SetNodeStmt(newNode, MakeStmt(newNode, assignLocExpr, 0)));
            }

            //--------------------------------------------------------
            // Get "Add" method.
            //--------------------------------------------------------
            MemberLookup mem = new MemberLookup();

            if (!mem.Lookup(
                    Compiler,
                    typeSym,
                    leftExpr,
                    this.parentDeclSym,
                    addMethName,
                    0,
                    MemLookFlagsEnum.UserCallable))
            {
                Compiler.Error(
                    newNode.TypeNode,
                    CSCERRID.ERR_NoSuchMember,
                    new ErrArg(typeSym),
                    new ErrArg("Add"));
                return(NewError(newNode, null));
            }
            if (mem.FirstSym == null || !mem.FirstSym.IsMETHSYM)
            {
                return(NewError(newNode, null));
            }

            TypeArray typeGroup = mem.GetAllTypes();

            EXPRMEMGRP grpExpr = NewExpr(
                newNode,
                EXPRKIND.MEMGRP,
                Compiler.MainSymbolManager.MethodGroupTypeSym) as EXPRMEMGRP;

            grpExpr.Name                = addMethName;
            grpExpr.SymKind             = SYMKIND.METHSYM;
            grpExpr.TypeArguments       = BSYMMGR.EmptyTypeArray;
            grpExpr.ParentTypeSym       = typeSym;
            grpExpr.MethPropSym         = null;
            grpExpr.ObjectExpr          = leftExpr;
            grpExpr.ContainingTypeArray = typeGroup;
            grpExpr.Flags              |= EXPRFLAG.USERCALLABLE;

            //--------------------------------------------------------
            // Add each value.
            //--------------------------------------------------------
            DebugUtil.Assert(newNode.InitialNode != null);
#if false
            BASENODE node = null;
            switch (newNode.InitialNode.Kind)
            {
            case NODEKIND.DECLSTMT:
                node = (newNode.InitialNode as DECLSTMTNODE).VariablesNode;
                break;

            case NODEKIND.UNOP:
                node = (newNode.InitialNode as UNOPNODE).Operand;
                break;

            default:
                DebugUtil.Assert(false);
                break;
            }
#endif
            BASENODE node = elementsNode;
            while (node != null)
            {
                BASENODE elementNode;
                if (node.Kind == NODEKIND.LIST)
                {
                    elementNode = node.AsLIST.Operand1;
                    node        = node.AsLIST.Operand2;
                }
                else
                {
                    elementNode = node;
                    node        = null;
                }

                //----------------------------------------------------
                // Bind the elements
                //----------------------------------------------------
                EXPR elementExpr = BindExpr(
                    elementNode,
                    BindFlagsEnum.RValueRequired);

                //----------------------------------------------------
                // Add the elements
                //----------------------------------------------------
                EXPR addExpr = BindGrpToArgs(newNode, bindFlags, grpExpr, elementExpr);

                if (addExpr != null)
                {
                    builder.Add(SetNodeStmt(newNode, MakeStmt(newNode, addExpr, 0)));
                }
            }

            return(leftExpr);
        }
Beispiel #16
0
        //------------------------------------------------------------
        // FUNCBREC.BindObjectInitializer
        //
        /// <summary></summary>
        /// <param name="newNode"></param>
        /// <param name="typeSym"></param>
        /// <param name="locVarSym"></param>
        /// <param name="objectExpr"></param>
        /// <param name="builder"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        internal EXPR BindObjectInitializer(
            NEWNODE newNode,
            TYPESYM typeSym,
            LOCVARSYM locVarSym,
            EXPR objectExpr,
            StatementListBuilder builder)
        {
            DebugUtil.Assert(newNode != null && typeSym != null && builder != null);
            DebugUtil.Assert(
                (locVarSym != null && objectExpr == null) ||
                (locVarSym == null && objectExpr != null));

            BindFlagsEnum bindFlags   = BindFlagsEnum.RValueRequired;
            string        localFormat = "<{0}><{1}>__local";

            //--------------------------------------------------------
            // Bind the local variable.
            //--------------------------------------------------------
            if (locVarSym == null)
            {
                string typeName = typeSym.IsAGGTYPESYM ?
                                  (typeSym as AGGTYPESYM).GetAggregate().Name :
                                  typeSym.Name;
                string locName = String.Format(localFormat, typeName, (this.localCount)++);

                locVarSym = Compiler.LocalSymbolManager.CreateLocalSym(
                    SYMKIND.LOCVARSYM,
                    locName,
                    this.currentScopeSym) as LOCVARSYM;
                locVarSym.TypeSym             = typeSym;
                locVarSym.LocSlotInfo.HasInit = true;
                locVarSym.DeclTreeNode        = newNode;

                StoreInCache(newNode, locName, locVarSym, null, true);
            }

            EXPR locVarExpr = BindToLocal(
                newNode,
                locVarSym,
                bindFlags | BindFlagsEnum.MemberSet);

            //--------------------------------------------------------
            // If objectExpr is not null, assign it to the local variable.
            //--------------------------------------------------------
            if (objectExpr != null)
            {
                EXPR assignLocExpr = BindAssignment(
                    newNode,
                    locVarExpr,
                    objectExpr,
                    false);

                builder.Add(SetNodeStmt(newNode, MakeStmt(newNode, assignLocExpr, 0)));
            }

            //--------------------------------------------------------
            // Assign each value.
            //--------------------------------------------------------
            DECLSTMTNODE decNode = newNode.InitialNode as DECLSTMTNODE;

            DebugUtil.Assert(decNode != null);
            BASENODE node = decNode.VariablesNode;

            while (node != null)
            {
                VARDECLNODE varDecl;
                if (node.Kind == NODEKIND.LIST)
                {
                    varDecl = node.AsLIST.Operand1 as VARDECLNODE;
                    node    = node.AsLIST.Operand2;
                }
                else
                {
                    varDecl = node as VARDECLNODE;
                    node    = null;
                }

                BINOPNODE assignNode = varDecl.ArgumentsNode as BINOPNODE;
                if (assignNode == null ||
                    assignNode.Operator != OPERATOR.ASSIGN ||
                    assignNode.Operand1 == null ||
                    assignNode.Operand1.Kind != NODEKIND.NAME ||
                    assignNode.Operand2 == null)
                {
                    continue;
                }

                //----------------------------------------------------
                // LHS
                //----------------------------------------------------
                NAMENODE nameNode = assignNode.Operand1 as NAMENODE;
                DebugUtil.Assert(nameNode != null);

                bindFlags = BindFlagsEnum.MemberSet;
                MemberLookup mem = new MemberLookup();

                EXPR leftExpr = null;
                if (mem.Lookup(
                        Compiler,
                        typeSym,
                        locVarExpr,
                        this.parentDeclSym,
                        nameNode.Name,
                        0,
                        MemLookFlagsEnum.UserCallable))
                {
                    SymWithType swt = mem.FirstSymWithType;
                    DebugUtil.Assert(swt != null && swt.IsNotNull);

                    switch (swt.Sym.Kind)
                    {
                    case SYMKIND.MEMBVARSYM:
                        leftExpr = BindToField(
                            assignNode,
                            locVarExpr,
                            FieldWithType.Convert(swt),
                            bindFlags);
                        break;

                    case SYMKIND.PROPSYM:
                        leftExpr = BindToProperty(
                            assignNode,
                            locVarExpr,
                            PropWithType.Convert(swt),
                            bindFlags,
                            null,
                            null);
                        break;

                    default:
                        leftExpr = NewError(nameNode, null);
                        break;
                    }
                }
                else
                {
                    mem.ReportErrors(nameNode);
                    leftExpr = NewError(nameNode, null);
                }

                //----------------------------------------------------
                // Collection initializer
                //----------------------------------------------------
                if (assignNode.Operand2.Kind == NODEKIND.ARRAYINIT)
                {
                    if (!leftExpr.TypeSym.IsARRAYSYM)
                    {
                        BindCollectionInitializer(
                            newNode,
                            (assignNode.Operand2 as UNOPNODE).Operand,
                            leftExpr.TypeSym, //typeSym,
                            null,             //locVarSym,
                            leftExpr,
                            null,
                            builder);
                        continue;
                    }
                }

                //----------------------------------------------------
                // RHS
                //----------------------------------------------------
                EXPR rightExpr = BindExpr(
                    assignNode.Operand2,
                    BindFlagsEnum.RValueRequired);

                //----------------------------------------------------
                // Assign
                //----------------------------------------------------
                EXPR assignExpr = BindAssignment(
                    assignNode,
                    leftExpr,
                    rightExpr,
                    false);

                builder.Add(SetNodeStmt(decNode, MakeStmt(decNode, assignExpr, 0)));
            }

            return(locVarExpr);
        }
Beispiel #17
0
        //------------------------------------------------------------
        // ReflectionUtil.IsTypeBuilderInstruction
        //
        /// <summary></summary>
        /// <param name="typeSym"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        internal static bool IsTypeBuilderInstruction(TYPESYM typeSym)
        {
            if (typeSym == null)
            {
                return(false);
            }
            Type type  = null;
            int  count = 0;
            int  index = 0;

            switch (typeSym.Kind)
            {
            //----------------------------------------------------
            // AGGTYPESYM
            //----------------------------------------------------
            case SYMKIND.AGGTYPESYM:
                AGGTYPESYM ats = typeSym as AGGTYPESYM;
                DebugUtil.Assert(ats != null);
                if (ats.AllTypeArguments == null ||
                    ats.AllTypeArguments.Count == 0)
                {
                    return(false);
                }

                AGGSYM aggSym = ats.GetAggregate();
                DebugUtil.Assert(aggSym != null);
                if (aggSym.TypeBuilder != null)
                {
                    return(true);
                }
                TypeArray typeArgs = ats.AllTypeArguments;
                for (int i = 0; i < typeArgs.Count; ++i)
                {
                    if (IsTypeBuilderInstruction(typeArgs[i]))
                    {
                        return(true);
                    }
                }
                return(false);

            //----------------------------------------------------
            // ARRAYSYM
            //----------------------------------------------------
            case SYMKIND.ARRAYSYM:
                return(IsTypeBuilderInstruction(typeSym.ParentSym as TYPESYM));

            //----------------------------------------------------
            // VOIDSYM
            //----------------------------------------------------
            case SYMKIND.VOIDSYM:
                return(false);

            //----------------------------------------------------
            // PARAMMODSYM
            //----------------------------------------------------
            case SYMKIND.PARAMMODSYM:
                return(IsTypeBuilderInstruction(typeSym.ParentSym as TYPESYM));

            //----------------------------------------------------
            // TYVARSYM
            //----------------------------------------------------
            case SYMKIND.TYVARSYM:
                return(true);

            //----------------------------------------------------
            // PTRSYM
            //----------------------------------------------------
            case SYMKIND.PTRSYM:
                return(IsTypeBuilderInstruction((typeSym as PTRSYM).BaseTypeSym));

            //----------------------------------------------------
            // NUBSYM
            //----------------------------------------------------
            case SYMKIND.NUBSYM:
                return(IsTypeBuilderInstruction((typeSym as NUBSYM).BaseTypeSym));

            //----------------------------------------------------
            // otherwise
            //----------------------------------------------------
            case SYMKIND.NULLSYM:
            case SYMKIND.ERRORSYM:
                break;

            case SYMKIND.MODOPTTYPESYM:
                throw new NotImplementedException("SymbolUtil.MakeSystemType: MODOPTTYPESYM");

            case SYMKIND.ANONMETHSYM:
            case SYMKIND.METHGRPSYM:
            case SYMKIND.UNITSYM:
                break;

            default:
                break;
            }
            return(false);
        }
Beispiel #18
0
        //------------------------------------------------------------
        // FUNCBREC.HasIEnumerable (2)
        //
        /// <summary>
        /// Rewrite HasIEnumerable for collection initializer.
        /// Return the IEnumerable or IEnumerable&lt;T&gt; instance.
        /// </summary>
        /// <param name="collection"></param>
        /// <param name="tree"></param>
        /// <param name="badType"></param>
        /// <param name="badMember"></param>
        /// <returns></returns>
        //------------------------------------------------------------
        private AGGTYPESYM HasIEnumerable(
            TYPESYM collectionTypeSym/*,
                                      * BASENODE treeNode,
                                      * TYPESYM badTypeSym,
                                      * PREDEFNAME badMemberName*/
            )
        {
            AGGTYPESYM ifaceCandidateAts = null;
            // First try the generic interfaces
            AGGSYM gEnumAggSym
                = Compiler.GetOptPredefAgg(PREDEFTYPE.G_IENUMERABLE, true);
            TypeArray  allIfacesTypeArray = null;
            AGGTYPESYM baseAts            = null;

            // If generics don't exist or the type isn't an AGGTYPESYM
            // then we can't check the interfaces (and base-class interfaces)
            // for IEnumerable<T> so immediately try the non-generic IEnumerable
            if (gEnumAggSym == null)
            {
                goto NO_GENERIC;
            }

            if (collectionTypeSym.IsAGGTYPESYM)
            {
                if (collectionTypeSym.GetAggregate() == gEnumAggSym ||
                    collectionTypeSym.IsPredefType(PREDEFTYPE.IENUMERABLE))
                {
                    DebugUtil.Assert(false, "IEnumerable/ator types are bad!");
                    goto LERROR;
                }

                AGGTYPESYM tempAts = collectionTypeSym as AGGTYPESYM;
                allIfacesTypeArray = tempAts.GetIfacesAll();
                baseAts            = tempAts.GetBaseClass();
            }
            else if (collectionTypeSym.IsTYVARSYM)
            {
                // Note:
                // we'll search the interface list before the class constraint,
                // but it doesn't matter since we require a unique instantiation of IEnumerable<T>.

                // Note:
                // The pattern search will usually find the interface constraint
                // - but if the class constraint has a non-public or non-applicable
                // or non-method GetEnumerator,
                // the interfaces are hidden in which case we will find them here.

                TYVARSYM tempTvSym = collectionTypeSym as TYVARSYM;
                allIfacesTypeArray = tempTvSym.AllInterfaces;
                baseAts            = tempTvSym.BaseClassSym;
            }
            else
            {
                goto NO_GENERIC;
            }

            DebugUtil.Assert(allIfacesTypeArray != null);

            // If the type implements exactly one instantiation of
            // IEnumerable<T> then it's the one.
            //
            // If it implements none then try the non-generic interface.
            //
            // If it implements more than one, then it's an error.
            //
            // Search the direct and indirect interfaces via allIfacesTypeArray,
            // going up the base chain...
            // Work up the base chain
            for (; ;)
            {
                // Now work across all the interfaces
                for (int i = 0; i < allIfacesTypeArray.Count; ++i)
                {
                    AGGTYPESYM iface = allIfacesTypeArray[i] as AGGTYPESYM;
                    if (iface.GetAggregate() == gEnumAggSym)
                    {
                        if (ifaceCandidateAts == null)
                        {
                            // First implementation
                            ifaceCandidateAts = iface;
                        }
                        else if (iface != ifaceCandidateAts)
                        {
                            // If this really is a different instantiation report an error
                            Compiler.Error(
                                treeNode,
                                CSCERRID.ERR_MultipleIEnumOfT,
                                new ErrArgRef(collectionTypeSym),
                                new ErrArg(gEnumAggSym.GetThisType()));
                            return(null);
                        }
                    }
                }
                // Check the base class.
                if (baseAts == null)
                {
                    break;
                }
                allIfacesTypeArray = baseAts.GetIfacesAll();
                baseAts            = baseAts.GetBaseClass();
            }

            // Report the one and only generic interface
            if (ifaceCandidateAts != null)
            {
                DebugUtil.Assert(
                    CanConvert(collectionTypeSym, ifaceCandidateAts, ConvertTypeEnum.NOUDC));
                return(ifaceCandidateAts);
            }

NO_GENERIC:
            if (collectionTypeSym.IsPredefType(PREDEFTYPE.IENUMERABLE))
            {
                DebugUtil.VsFail("Why didn't IEnumerator match the pattern?");
                goto LERROR;
            }

            // No errors, no generic interfaces, try the non-generic interface
            ifaceCandidateAts = GetRequiredPredefinedType(PREDEFTYPE.IENUMERABLE);
            if (CanConvert(collectionTypeSym, ifaceCandidateAts, ConvertTypeEnum.NOUDC))
            {
                return(ifaceCandidateAts);
            }

LERROR:
            return(null);
        }
Beispiel #19
0
        //------------------------------------------------------------
        // MetaDataHelper.GetExplicitImplTypeName
        //
        /// <summary></summary>
        /// <param name="typeSym"></param>
        /// <param name="strBuilder"></param>
        //------------------------------------------------------------
        public void GetExplicitImplTypeName(TYPESYM typeSym, StringBuilder strBuilder)
        {
#if DEBUG
            if (!(typeSym != null))
            {
                ;
            }
#endif
            DebugUtil.Assert(typeSym != null);

            TYPESYM   nakedTypeSym = typeSym.GetNakedType(false);
            TypeArray typeArgs     = null;

            switch (nakedTypeSym.Kind)
            {
            default:
                DebugUtil.Assert(false, "Unhandled type in GetExplicitImplTypeName");
                return;

            case SYMKIND.TYVARSYM:
                strBuilder.Append(nakedTypeSym.Name);
                break;

            case SYMKIND.NUBSYM:
                nakedTypeSym = (nakedTypeSym as NUBSYM).GetAggTypeSym();
                if (nakedTypeSym == null)
                {
                    DebugUtil.Assert(false, "Why did GetAts return null?");
                    return;
                }
                // Fall through.
                goto case SYMKIND.AGGTYPESYM;

            case SYMKIND.AGGTYPESYM:
            {
                AGGTYPESYM outerAggTypeSym = (nakedTypeSym as AGGTYPESYM).OuterTypeSym;
                AGGSYM     aggSym          = nakedTypeSym.GetAggregate();

                if (outerAggTypeSym != null)
                {
                    GetExplicitImplTypeName(outerAggTypeSym, strBuilder);
                    strBuilder.Append('.');
                }
                else
                {
                    DebugUtil.Assert(aggSym.ParentBagSym != null && !aggSym.ParentBagSym.IsAGGSYM);
                    int cch = strBuilder.Length;
                    GetFullName(aggSym.ParentBagSym, strBuilder, aggSym);
                    if (cch < strBuilder.Length)
                    {
                        strBuilder.Append('.');
                    }
                }
                strBuilder.Append(aggSym.Name);

                typeArgs = (nakedTypeSym as AGGTYPESYM).TypeArguments;
            }
            break;

            case SYMKIND.ERRORSYM:
            {
                ERRORSYM errSym    = nakedTypeSym as ERRORSYM;
                SYM      parentSym = errSym.ParentSym;

                if (parentSym != null && parentSym.IsTYPESYM)
                {
                    GetExplicitImplTypeName(parentSym as TYPESYM, strBuilder);
                    strBuilder.Append('.');
                }
                else if (parentSym != null && parentSym.IsNSAIDSYM)
                {
                    parentSym = (parentSym as NSAIDSYM).NamespaceSym;
                    int cch = strBuilder.Length;
                    GetFullName(parentSym, strBuilder, errSym);
                    if (cch < strBuilder.Length)
                    {
                        strBuilder.Append('.');
                    }
                }
                strBuilder.Append(errSym.ErrorName);

                typeArgs = errSym.TypeArguments;
            }
            break;
            }

            if (typeArgs != null && typeArgs.Count > 0)
            {
                strBuilder.Append('<');
                for (int i = 0; i < typeArgs.Count; ++i)
                {
                    if (i > 0)
                    {
                        strBuilder.Append(',');
                    }
                    GetExplicitImplTypeName(typeArgs[i], strBuilder);
                }
                strBuilder.Append('>');
            }

            // Add ptr and array modifiers
            AddTypeModifiers(typeSym, strBuilder);
        }
        //------------------------------------------------------------
        // FUNCBREC.BindImplicitlyTypedArrayInitConvert
        //
        /// <summary></summary>
        /// <param name="elementTypeSym"></param>
        /// <param name="dimList"></param>
        /// <param name="dimIndex"></param>
        /// <param name="argListExpr"></param>
        /// <param name="nonConstCount"></param>
        /// <param name="constCount"></param>
        /// <param name="hasSideEffects"></param>
        //------------------------------------------------------------
        internal void BindImplicitlyTypedArrayInitConvert(
            TYPESYM elementTypeSym,
            List <int> dimList,
            int dimIndex,
            ref EXPR argListExpr,
            ref int nonConstCount,
            ref int constCount,
            ref bool hasSideEffects)
        {
            int count = 0;

            EXPR nodeExpr = argListExpr;
            EXPR topArgList = null, lastArgList = null;

            while (nodeExpr != null)
            {
                EXPR argExpr;
                if (nodeExpr.Kind == EXPRKIND.LIST)
                {
                    EXPRBINOP listExpr = nodeExpr as EXPRBINOP;
                    argExpr  = listExpr.Operand1;
                    nodeExpr = listExpr.Operand2;
                }
                else
                {
                    argExpr  = nodeExpr;
                    nodeExpr = null;
                }
                count++;

                EXPR expr = null;
#if false
                expr = MustConvert(
                    argExpr,
                    elementTypeSym,
                    0);
#endif
                if (!BindImplicitConversion(
                        argExpr.TreeNode,
                        argExpr,
                        argExpr.TypeSym,
                        elementTypeSym,
                        ref expr,
                        0))
                {
                    Compiler.Error(argExpr.TreeNode, CSCERRID.ERR_NoBestTypeForArray);
                    expr = NewError(treeNode, elementTypeSym);
                }

                EXPR constExpr = expr.GetConst();
                if (constExpr != null)
                {
                    if (!constExpr.IsZero(true))
                    {
                        ++constCount;
                    }
                    if (expr.HasSideEffects(Compiler))
                    {
                        hasSideEffects = true;
                    }
                }
                else
                {
                    nonConstCount++;
                }
                NewList(expr, ref topArgList, ref lastArgList);
                //exprList.Add(expr);
            }
            argListExpr = topArgList;
        }