///////////////////////////////////////////////////////////////////////////////// // 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)); }
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)); }
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 })); }
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()); }
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); }
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); }
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); }
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)); }
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)); }
/*************************************************************************************************** * 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); }
public override AggregateType GetAts() => SymbolLoader.GetPredefindType(PredefinedType.PT_ARRAY);