예제 #1
0
        /////////////////////////////////////////////////////////////////////////////////
        // Expression types.

        private ExprBinOp VisitBoundLambda(ExprBoundLambda anonmeth)
        {
            Debug.Assert(anonmeth != null);

            MethodSymbol  lambdaMethod     = GetPreDefMethod(PREDEFMETH.PM_EXPRESSION_LAMBDA);
            AggregateType delegateType     = anonmeth.DelegateType;
            TypeArray     lambdaTypeParams = TypeArray.Allocate(delegateType);
            AggregateType expressionType   = SymbolLoader.GetPredefindType(PredefinedType.PT_EXPRESSION);
            MethWithInst  mwi = new MethWithInst(lambdaMethod, expressionType, lambdaTypeParams);
            Expr          createParameters = CreateWraps(anonmeth);

            Debug.Assert(createParameters != null);
            Debug.Assert(anonmeth.Expression != null);
            Expr body = Visit(anonmeth.Expression);

            Debug.Assert(anonmeth.ArgumentScope.nextChild == null);
            Expr            parameters = GenerateParamsArray(null, PredefinedType.PT_PARAMETEREXPRESSION);
            Expr            args       = ExprFactory.CreateList(body, parameters);
            CType           typeRet    = TypeManager.SubstType(mwi.Meth().RetType, mwi.GetType(), mwi.TypeArgs);
            ExprMemberGroup pMemGroup  = ExprFactory.CreateMemGroup(null, mwi);
            ExprCall        call       = ExprFactory.CreateCall(0, typeRet, args, pMemGroup, mwi);

            call.PredefinedMethod = PREDEFMETH.PM_EXPRESSION_LAMBDA;
            return(ExprFactory.CreateSequence(createParameters, call));
        }
예제 #2
0
        private static Expr GenerateParameter(string name, CType CType)
        {
            SymbolLoader.GetPredefindType(PredefinedType.PT_STRING);  // force an ensure state
            ExprConstant nameString = ExprFactory.CreateStringConstant(name);
            ExprTypeOf   pTypeOf    = CreateTypeOf(CType);

            return(GenerateCall(PREDEFMETH.PM_EXPRESSION_PARAMETER, pTypeOf, nameString));
        }
예제 #3
0
        private static ExprArrayInit GenerateParamsArray(Expr args, PredefinedType pt)
        {
            int           parameterCount         = ExpressionIterator.Count(args);
            AggregateType paramsArrayElementType = SymbolLoader.GetPredefindType(pt);
            ArrayType     paramsArrayType        = TypeManager.GetArray(paramsArrayElementType, 1, true);
            ExprConstant  paramsArrayArg         = ExprFactory.CreateIntegerConstant(parameterCount);

            return(ExprFactory.CreateArrayInit(paramsArrayType, args, paramsArrayArg, new int[] { parameterCount }));
        }
예제 #4
0
        public bool Lookup(CType typeSrc, Expr obj, ParentSymbol symWhere, Name name, int arity, MemLookFlags flags)
        {
            Debug.Assert((flags & ~MemLookFlags.All) == 0);
            Debug.Assert(obj == null || obj.Type != null);
            Debug.Assert(typeSrc is AggregateType);

            _prgtype = _rgtypeStart;

            // Save the inputs for error handling, etc.
            _typeSrc  = typeSrc;
            _symWhere = symWhere;
            _name     = name;
            _arity    = arity;
            _flags    = flags;

            _typeQual = (_flags & MemLookFlags.Ctor) != 0 ? _typeSrc : obj?.Type;

            // Determine what to search.
            AggregateType typeCls1;
            AggregateType typeIface;
            TypeArray     ifaces;

            if (typeSrc.IsInterfaceType)
            {
                Debug.Assert((_flags & (MemLookFlags.Ctor | MemLookFlags.NewObj | MemLookFlags.Operator | MemLookFlags.BaseCall)) == 0);
                typeCls1  = null;
                typeIface = (AggregateType)typeSrc;
                ifaces    = typeIface.IfacesAll;
            }
            else
            {
                typeCls1  = (AggregateType)typeSrc;
                typeIface = null;
                ifaces    = TypeArray.Empty;
            }

            AggregateType typeCls2 = typeIface != null || ifaces.Count > 0
                ? SymbolLoader.GetPredefindType(PredefinedType.PT_OBJECT)
                : null;

            // Search the class first (except possibly object).
            if (typeCls1 == null || LookupInClass(typeCls1, ref typeCls2))
            {
                // Search the interfaces.
                if ((typeIface != null || ifaces.Count > 0) && LookupInInterfaces(typeIface, ifaces) && typeCls2 != null)
                {
                    // Search object last.
                    Debug.Assert(typeCls2 != null && typeCls2.IsPredefType(PredefinedType.PT_OBJECT));

                    AggregateType result = null;
                    LookupInClass(typeCls2, ref result);
                }
            }

            return(!FError());
        }
예제 #5
0
        private static ExprCall GenerateCall(PREDEFMETH pdm, Expr arg1, Expr arg2, Expr arg3, Expr arg4)
        {
            MethodSymbol method = GetPreDefMethod(pdm);

            if (method == null)
            {
                return(null);
            }
            AggregateType   expressionType = SymbolLoader.GetPredefindType(PredefinedType.PT_EXPRESSION);
            Expr            args           = ExprFactory.CreateList(arg1, arg2, arg3, arg4);
            MethWithInst    mwi            = new MethWithInst(method, expressionType);
            ExprMemberGroup pMemGroup      = ExprFactory.CreateMemGroup(null, mwi);
            ExprCall        call           = ExprFactory.CreateCall(0, mwi.Meth().RetType, args, pMemGroup, mwi);

            call.PredefinedMethod = pdm;
            return(call);
        }
예제 #6
0
        private static ExprCall GenerateCall(PREDEFMETH pdm, Expr arg1)
        {
            MethodSymbol method = GetPreDefMethod(pdm);

            // this should be enforced in an earlier pass and the transform pass should not
            // be handling this error
            if (method == null)
            {
                return(null);
            }
            AggregateType   expressionType = SymbolLoader.GetPredefindType(PredefinedType.PT_EXPRESSION);
            MethWithInst    mwi            = new MethWithInst(method, expressionType);
            ExprMemberGroup pMemGroup      = ExprFactory.CreateMemGroup(null, mwi);
            ExprCall        call           = ExprFactory.CreateCall(0, mwi.Meth().RetType, arg1, pMemGroup, mwi);

            call.PredefinedMethod = pdm;
            return(call);
        }
예제 #7
0
        private Expr GenerateIndexList(Expr oldIndices)
        {
            CType intType = symbolLoader.GetPredefindType(PredefinedType.PT_INT);

            Expr newIndices     = null;
            Expr newIndicesTail = newIndices;

            for (ExpressionIterator it = new ExpressionIterator(oldIndices); !it.AtEnd(); it.MoveNext())
            {
                Expr newIndex = it.Current();
                if (newIndex.Type != intType)
                {
                    newIndex        = expressionFactory.CreateCast(EXPRFLAG.EXF_INDEXEXPR, intType, newIndex);
                    newIndex.Flags |= EXPRFLAG.EXF_CHECKOVERFLOW;
                }
                Expr rewrittenIndex = Visit(newIndex);
                expressionFactory.AppendItemToList(rewrittenIndex, ref newIndices, ref newIndicesTail);
            }
            return(newIndices);
        }
예제 #8
0
        protected override Expr VisitCONCAT(ExprConcat expr)
        {
            Debug.Assert(expr != null);
            PREDEFMETH pdm;

            if (expr.FirstArgument.Type.IsPredefType(PredefinedType.PT_STRING) && expr.SecondArgument.Type.IsPredefType(PredefinedType.PT_STRING))
            {
                pdm = PREDEFMETH.PM_STRING_CONCAT_STRING_2;
            }
            else
            {
                pdm = PREDEFMETH.PM_STRING_CONCAT_OBJECT_2;
            }
            Expr         p1         = Visit(expr.FirstArgument);
            Expr         p2         = Visit(expr.SecondArgument);
            MethodSymbol method     = GetPreDefMethod(pdm);
            Expr         methodInfo = ExprFactory.CreateMethodInfo(method, SymbolLoader.GetPredefindType(PredefinedType.PT_STRING), null);

            return(GenerateCall(PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED, p1, p2, methodInfo));
        }
예제 #9
0
        private static Expr GenerateConstant(Expr expr)
        {
            EXPRFLAG flags = 0;

            AggregateType pObject = SymbolLoader.GetPredefindType(PredefinedType.PT_OBJECT);

            if (expr.Type is NullType)
            {
                ExprTypeOf pTypeOf = CreateTypeOf(pObject);
                return(GenerateCall(PREDEFMETH.PM_EXPRESSION_CONSTANT_OBJECT_TYPE, expr, pTypeOf));
            }

            AggregateType stringType = SymbolLoader.GetPredefindType(PredefinedType.PT_STRING);

            if (expr.Type != stringType)
            {
                flags = EXPRFLAG.EXF_BOX;
            }

            ExprCast   cast     = ExprFactory.CreateCast(flags, pObject, expr);
            ExprTypeOf pTypeOf2 = CreateTypeOf(expr.Type);

            return(GenerateCall(PREDEFMETH.PM_EXPRESSION_CONSTANT_OBJECT_TYPE, cast, pTypeOf2));
        }
예제 #10
0
        /***************************************************************************************************
        *   Determine whether there is an explicit or implicit reference conversion (or identity conversion)
        *   from typeSrc to typeDst. This is when:
        *
        *  13.2.3 Explicit reference conversions
        *
        *  The explicit reference conversions are:
        *   From object to any reference-type.
        *   From any class-type S to any class-type T, provided S is a base class of T.
        *   From any class-type S to any interface-type T, provided S is not sealed and provided S does not implement T.
        *   From any interface-type S to any class-type T, provided T is not sealed or provided T implements S.
        *   From any interface-type S to any interface-type T, provided S is not derived from T.
        *   From an array-type S with an element type SE to an array-type T with an element type TE, provided all of the following are true:
        *   o   S and T differ only in element type. (In other words, S and T have the same number of dimensions.)
        *   o   An explicit reference conversion exists from SE to TE.
        *   From System.Array and the interfaces it implements, to any array-type.
        *   From System.Delegate and the interfaces it implements, to any delegate-type.
        *   From a one-dimensional array-type S[] to System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyList<T> and their base interfaces, provided there is an explicit reference conversion from S to T.
        *   From a generic delegate type S to generic delegate type  T, provided all of the follow are true:
        *   o Both types are constructed generic types of the same generic delegate type, D<X1,... Xk>.That is,
        *     S is D<S1,... Sk> and T is D<T1,... Tk>.
        *   o S is not compatible with or identical to T.
        *   o If type parameter Xi is declared to be invariant then Si must be identical to Ti.
        *   o If type parameter Xi is declared to be covariant ("out") then Si must be convertible
        *     to Ti via an identify conversion,  implicit reference conversion, or explicit reference conversion.
        *   o If type parameter Xi is declared to be contravariant ("in") then either Si must be identical to Ti,
        *      or Si and Ti must both be reference types.
        *   From System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyList<T> and their base interfaces to a one-dimensional array-type S[], provided there is an implicit or explicit reference conversion from S[] to System.Collections.Generic.IList<T> or System.Collections.Generic.IReadOnlyList<T>. This is precisely when either S and T are the same type or there is an implicit or explicit reference conversion from S to T.
        *
        *  For a type-parameter T that is known to be a reference type (25.7), the following explicit reference conversions exist:
        *   From the effective base class C of T to T and from any base class of C to T.
        *   From any interface-type to T.
        *   From T to any interface-type I provided there isn't already an implicit reference conversion from T to I.
        *   From a type-parameter U to T provided that T depends on U (25.7). [Note: Since T is known to be a reference type, within the scope of T, the run-time type of U will always be a reference type, even if U is not known to be a reference type at compile-time. end note]
        *
        * Both src and dst are reference types and there is a builtin explicit conversion from
        *     src to dst.
        * Or src is a reference type and dst is a base type of src (in which case the conversion is
        *     implicit as well).
        * Or dst is a reference type and src is a base type of dst.
        *
        *   The latter two cases can happen with type variables even though the other type variable is not
        *   a reference type.
        ***************************************************************************************************/
        public static bool FExpRefConv(CType typeSrc, CType typeDst)
        {
            Debug.Assert(typeSrc != null);
            Debug.Assert(typeDst != null);
            if (typeSrc.IsReferenceType && typeDst.IsReferenceType)
            {
                // is there an implicit reference conversion in either direction?
                // this handles the bulk of the cases ...
                if (SymbolLoader.HasIdentityOrImplicitReferenceConversion(typeSrc, typeDst) ||
                    SymbolLoader.HasIdentityOrImplicitReferenceConversion(typeDst, typeSrc))
                {
                    return(true);
                }

                // For a type-parameter T that is known to be a reference type (25.7), the following explicit reference conversions exist:
                // *    From any interface-type to T.
                // *    From T to any interface-type I provided there isn't already an implicit reference conversion from T to I.
                if (typeSrc.IsInterfaceType && typeDst is TypeParameterType || typeSrc is TypeParameterType && typeDst.IsInterfaceType)
                {
                    return(true);
                }

                // * From any class-type S to any interface-type T, provided S is not sealed
                // * From any interface-type S to any class-type T, provided T is not sealed
                // * From any interface-type S to any interface-type T, provided S is not derived from T.
                if (typeSrc is AggregateType atSrc && typeDst is AggregateType atDst)
                {
                    AggregateSymbol aggSrc  = atSrc.OwningAggregate;
                    AggregateSymbol aggDest = atDst.OwningAggregate;

                    if ((aggSrc.IsClass() && !aggSrc.IsSealed() && aggDest.IsInterface()) ||
                        (aggSrc.IsInterface() && aggDest.IsClass() && !aggDest.IsSealed()) ||
                        (aggSrc.IsInterface() && aggDest.IsInterface()))
                    {
                        return(true);
                    }
                }

                if (typeSrc is ArrayType arrSrc)
                {
                    // *    From an array-type S with an element type SE to an array-type T with an element type TE, provided all of the following are true:
                    //     o    S and T differ only in element type. (In other words, S and T have the same number of dimensions.)
                    //     o    An explicit reference conversion exists from SE to TE.
                    if (typeDst is ArrayType arrDst)
                    {
                        return(arrSrc.Rank == arrDst.Rank &&
                               arrSrc.IsSZArray == arrDst.IsSZArray &&
                               FExpRefConv(arrSrc.ElementType, arrDst.ElementType));
                    }

                    // *    From a one-dimensional array-type S[] to System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyList<T>
                    //      and their base interfaces, provided there is an explicit reference conversion from S to T.
                    if (!arrSrc.IsSZArray || !typeDst.IsInterfaceType)
                    {
                        return(false);
                    }

                    AggregateType aggDst      = (AggregateType)typeDst;
                    TypeArray     typeArgsAll = aggDst.TypeArgsAll;

                    if (typeArgsAll.Count != 1)
                    {
                        return(false);
                    }

                    AggregateSymbol aggIList         = SymbolLoader.GetPredefAgg(PredefinedType.PT_G_ILIST);
                    AggregateSymbol aggIReadOnlyList = SymbolLoader.GetPredefAgg(PredefinedType.PT_G_IREADONLYLIST);

                    if ((aggIList == null ||
                         !SymbolLoader.IsBaseAggregate(aggIList, aggDst.OwningAggregate)) &&
                        (aggIReadOnlyList == null ||
                         !SymbolLoader.IsBaseAggregate(aggIReadOnlyList, aggDst.OwningAggregate)))
                    {
                        return(false);
                    }

                    return(FExpRefConv(arrSrc.ElementType, typeArgsAll[0]));
                }

                if (typeDst is ArrayType arrayDest && typeSrc is AggregateType aggtypeSrc)
                {
                    // * From System.Array and the interfaces it implements, to any array-type.
                    if (SymbolLoader.HasIdentityOrImplicitReferenceConversion(SymbolLoader.GetPredefindType(PredefinedType.PT_ARRAY), typeSrc))
                    {
                        return(true);
                    }

                    // *    From System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyList<T> and their base interfaces to a
                    //      one-dimensional array-type S[], provided there is an implicit or explicit reference conversion from S[] to
                    //      System.Collections.Generic.IList<T> or System.Collections.Generic.IReadOnlyList<T>. This is precisely when either S and T
                    //      are the same type or there is an implicit or explicit reference conversion from S to T.
                    if (!arrayDest.IsSZArray || !typeSrc.IsInterfaceType || aggtypeSrc.TypeArgsAll.Count != 1)
                    {
                        return(false);
                    }

                    AggregateSymbol aggIList         = SymbolLoader.GetPredefAgg(PredefinedType.PT_G_ILIST);
                    AggregateSymbol aggIReadOnlyList = SymbolLoader.GetPredefAgg(PredefinedType.PT_G_IREADONLYLIST);

                    if ((aggIList == null ||
                         !SymbolLoader.IsBaseAggregate(aggIList, aggtypeSrc.OwningAggregate)) &&
                        (aggIReadOnlyList == null ||
                         !SymbolLoader.IsBaseAggregate(aggIReadOnlyList, aggtypeSrc.OwningAggregate)))
                    {
                        return(false);
                    }

                    CType typeArr = arrayDest.ElementType;
                    CType typeLst = aggtypeSrc.TypeArgsAll[0];

                    Debug.Assert(!(typeArr is MethodGroupType));
                    return(typeArr == typeLst || FExpRefConv(typeArr, typeLst));
                }
                if (HasGenericDelegateExplicitReferenceConversion(typeSrc, typeDst))
                {
                    return(true);
                }
            }
            else if (typeSrc.IsReferenceType)
            {
                // conversion of T . U, where T : class, U
                // .. these constraints implies where U : class
                return(SymbolLoader.HasIdentityOrImplicitReferenceConversion(typeSrc, typeDst));
            }
            else if (typeDst.IsReferenceType)
            {
                // conversion of T . U, where U : class, T
                // .. these constraints implies where T : class
                return(SymbolLoader.HasIdentityOrImplicitReferenceConversion(typeDst, typeSrc));
            }
            return(false);
        }
예제 #11
0
 public override AggregateType GetAts() => SymbolLoader.GetPredefindType(PredefinedType.PT_ARRAY);