コード例 #1
0
        public static Expression ImplicitNullableConversion(ParseContext ec, Expression expr, Type targetType)
        {
            Type exprType = expr.Type;

            //
            // From null to any nullable type
            //
            if (exprType == TypeManager.CoreTypes.Null)
            {
                return(ec == null ? EmptyExpression.Null : LiftedNullExpression.Create(targetType, expr.Span));
            }

            // S -> T?
            var elementType = targetType.GetGenericArguments()[0];

            // S? -> T?
            if (TypeManager.IsNullableType(exprType))
            {
                exprType = exprType.GetGenericArguments()[0];
            }

            //
            // Predefined implicit identity or implicit numeric conversion
            // has to exist between underlying type S and underlying type T
            //

            // Handles probing
            if (ec == null)
            {
                if (exprType == elementType)
                {
                    return(EmptyExpression.Null);
                }

                return(MakeImplicitNumericConversion(ec, null, exprType, elementType));
            }

            Expression unwrap;

            if (exprType != expr.Type)
            {
                unwrap = Unwrap.Create(expr);
            }
            else
            {
                unwrap = expr;
            }

            Expression conv = exprType == elementType ? unwrap : MakeImplicitNumericConversion(ec, unwrap, exprType, elementType);

            if (conv == null)
            {
                return(null);
            }

            if (exprType != expr.Type)
            {
                return(new LiftedExpression(conv, unwrap, targetType).Resolve(ec));
            }

            // Do constant optimization for S -> T?
            if (unwrap is ConstantExpression)
            {
                conv = ((ConstantExpression)unwrap).ConvertImplicitly(elementType);
            }

            return(Wrap.Create(conv, targetType));
        }
コード例 #2
0
        public static ConstantExpression Constantify(Type t)
        {
            if (t == TypeManager.CoreTypes.Int32)
            {
                return(new ConstantExpression <int>(0));
            }
            if (t == TypeManager.CoreTypes.UInt32)
            {
                return(new ConstantExpression <uint>(0u));
            }
            if (t == TypeManager.CoreTypes.Int64)
            {
                return(new ConstantExpression <long>(0L));
            }
            if (t == TypeManager.CoreTypes.UInt64)
            {
                return(new ConstantExpression <ulong>(0uL));
            }
            if (t == TypeManager.CoreTypes.Single)
            {
                return(new ConstantExpression <float>(0f));
            }
            if (t == TypeManager.CoreTypes.Double)
            {
                return(new ConstantExpression <double>(0d));
            }
            if (t == TypeManager.CoreTypes.Int16)
            {
                return(new ConstantExpression <short>(0));
            }
            if (t == TypeManager.CoreTypes.UInt16)
            {
                return(new ConstantExpression <ushort>(0));
            }
            if (t == TypeManager.CoreTypes.SByte)
            {
                return(new ConstantExpression <sbyte>(0));
            }
            if (t == TypeManager.CoreTypes.Byte)
            {
                return(new ConstantExpression <byte>(0));
            }
            if (t == TypeManager.CoreTypes.Char)
            {
                return(new ConstantExpression <char>('\0'));
            }
            if (t == TypeManager.CoreTypes.Boolean)
            {
                return(new ConstantExpression <bool>(false));
            }
            if (t == TypeManager.CoreTypes.Decimal)
            {
                return(new ConstantExpression <decimal>(0m));
            }
            if (TypeManager.IsEnumType(t))
            {
                return(new EnumConstantExpression(Constantify(Enum.GetUnderlyingType(t)), t));
            }
            if (TypeManager.IsNullableType(t))
            {
                return(LiftedNullExpression.Create(t, SourceSpan.None));
            }

            return(null);
        }
コード例 #3
0
        Expression LiftResult(ParseContext ec, Expression res_expr)
        {
            TypeExpression lifted_type;

            //
            // Avoid double conversion
            //
            if (left_unwrap == null || left_null_lifted || !TypeManager.IsEqual(left_unwrap.Type, Left.Type) || (left_unwrap != null && right_null_lifted))
            {
                lifted_type = new NullableTypeExpression(Left.Type, Span);
                lifted_type = lifted_type.ResolveAsTypeTerminal(ec, false);
                if (lifted_type == null)
                {
                    return(null);
                }

                if (Left is CastExpression)
                {
                    ((CastExpression)Left).DestinationType = new TypeExpression(lifted_type.Type);
                }
                else
                {
                    Left = EmptyCastExpression.Create(Left, lifted_type.Type);
                }
            }

            if (right_unwrap == null || right_null_lifted || !TypeManager.IsEqual(right_unwrap.Type, Right.Type) || (right_unwrap != null && left_null_lifted))
            {
                lifted_type = new NullableTypeExpression(Right.Type, Span);
                lifted_type = lifted_type.ResolveAsTypeTerminal(ec, false);

                if (lifted_type == null)
                {
                    return(null);
                }

                if (Right is CastExpression)
                {
                    ((CastExpression)Right).DestinationType = new TypeExpression(lifted_type.Type);
                }
                else
                {
                    Right = EmptyCastExpression.Create(Right, lifted_type.Type);
                }
            }

            if (!Operator.IsComparison())
            {
                lifted_type = new NullableTypeExpression(res_expr.Type, Span);
                lifted_type = lifted_type.ResolveAsTypeTerminal(ec, false);

                if (lifted_type == null)
                {
                    return(null);
                }

                wrap_ctor  = new NullableInfo(lifted_type.Type).Constructor;
                ResultType = res_expr.Type = lifted_type.Type;
            }

            if (left_null_lifted)
            {
                Left = LiftedNullExpression.Create(Right.Type, Left.Span);

                if (Operator.IsArithmetic() || Operator.IsShift() || Operator.IsBitwise())
                {
                    return(LiftedNullExpression.CreateFromExpression(ec, res_expr));
                }

                //
                // Value types and null comparison
                //
                if (right_unwrap == null || Operator.IsRelational())
                {
                    return(CreateNullConstant(ec, right_orig).Resolve(ec));
                }
            }

            if (right_null_lifted)
            {
                Right = LiftedNullExpression.Create(Left.Type, Right.Span);

                if (Operator.IsArithmetic() || Operator.IsShift() || Operator.IsBitwise())
                {
                    return(LiftedNullExpression.CreateFromExpression(ec, res_expr));
                }

                //
                // Value types and null comparison
                //
                if (left_unwrap == null || Operator.IsRelational())
                {
                    return(CreateNullConstant(ec, left_orig).Resolve(ec));
                }
            }

            return(res_expr);
        }