Beispiel #1
0
        private Expr GenerateUserDefinedConversion(Expr arg, CType CType, Expr target, MethWithInst method)
        {
            // The user-defined explicit conversion from enum? to decimal or decimal? requires
            // that we convert the enum? to its nullable underlying CType.
            if (isEnumToDecimalConversion(arg.Type, CType))
            {
                // Special case: If we have enum? to decimal? then we need to emit
                // a conversion from enum? to its nullable underlying CType first.
                // This is unfortunate; we ought to reorganize how conversions are
                // represented in the Expr tree so that this is more transparent.

                // converting an enum to its underlying CType never fails, so no need to check it.
                CType underlyingType = arg.Type.StripNubs().underlyingEnumType();
                CType nullableType   = GetSymbolLoader().GetTypeManager().GetNullable(underlyingType);
                Expr  typeofNubEnum  = CreateTypeOf(nullableType);
                target = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, target, typeofNubEnum);
            }

            // If the methodinfo does not return the target CType AND this is not a lifted conversion
            // from one value CType to another, then we need to wrap the whole thing in another conversion,
            // e.g. if we have a user-defined conversion from int to S? and we have (S)myint, then we need to generate
            // Convert(Convert(myint, typeof(S?), op_implicit), typeof(S))

            CType pMethodReturnType = GetSymbolLoader().GetTypeManager().SubstType(method.Meth().RetType,
                                                                                   method.GetType(), method.TypeArgs);
            bool fDontLiftReturnType = (pMethodReturnType == CType || (IsNullableValueType(arg.Type) && IsNullableValueType(CType)));

            Expr       typeofInner = CreateTypeOf(fDontLiftReturnType ? CType : pMethodReturnType);
            Expr       methodInfo  = GetExprFactory().CreateMethodInfo(method);
            PREDEFMETH pdmInner    = arg.isChecked() ? PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_CONVERT_USER_DEFINED;
            Expr       callUserDefinedConversion = GenerateCall(pdmInner, target, typeofInner, methodInfo);

            if (fDontLiftReturnType)
            {
                return(callUserDefinedConversion);
            }

            PREDEFMETH pdmOuter    = arg.isChecked() ? PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED : PREDEFMETH.PM_EXPRESSION_CONVERT;
            Expr       typeofOuter = CreateTypeOf(CType);

            return(GenerateCall(pdmOuter, callUserDefinedConversion, typeofOuter));
        }
Beispiel #2
0
 private Expr GenerateConversion(Expr arg, CType CType, bool bChecked)
 {
     return(GenerateConversionWithSource(Visit(arg), CType, bChecked || arg.isChecked()));
 }