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)); }
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); }
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); }