}
static EmptyExpression MyEmptyExpr;
- static public Expression ImplicitReferenceConversion (EmitContext ec, Expression expr, Type target_type)
+ static public Expression WideningReferenceConversion (EmitContext ec, Expression expr, Type target_type)
{
Type expr_type = expr.Type;
return new EmptyCast (expr, target_type);
}
- // This code is kind of mirrored inside ImplicitStandardConversionExists
+ // This code is kind of mirrored inside WideningStandardConversionExists
// with the small distinction that we only probe there
//
// Always ensure that the code here and there is in sync
if (!target_type.IsValueType)
return new NullCast (expr, target_type);
+
+ // VB.NET specific: Convert Nothing to value types
+
+ Expression e = NothingToPrimitiveConstants (expr, target_type);
+ if (e != null)
+ return e;
+
+ return new NullCast (expr, target_type);
}
// from any class-type S to any interface-type T.
else
return null;
}
-
+
// from an array-type S to an array-type of type T
if (expr_type.IsArray && target_type.IsArray) {
if (expr_type.GetArrayRank () == target_type.GetArrayRank ()) {
Type target_element_type = TypeManager.GetElementType (target_type);
if (!expr_element_type.IsValueType && !target_element_type.IsValueType)
- if (ImplicitStandardConversionExists (ConstantEC, MyEmptyExpr,
+ if (WideningStandardConversionExists (ConstantEC, MyEmptyExpr,
target_element_type))
return new EmptyCast (expr, target_type);
}
// from an array-type to System.Array
if (expr_type.IsArray && target_type == TypeManager.array_type)
return new EmptyCast (expr, target_type);
-
+
+ // from an array-type of type T to IEnumerable<T>
+ if (expr_type.IsArray && TypeManager.IsIEnumerable (expr_type, target_type))
+ return new EmptyCast (expr, target_type);
+
// from any delegate type to System.Delegate
if ((expr_type == TypeManager.delegate_type || TypeManager.IsDelegateType (expr_type)) &&
target_type == TypeManager.delegate_type)
// Tests whether an implicit reference conversion exists between expr_type
// and target_type
//
- public static bool ImplicitReferenceConversionExists (EmitContext ec, Expression expr, Type target_type)
+ public static bool WideningReferenceConversionExists (EmitContext ec, Expression expr, Type target_type)
{
Type expr_type = expr.Type;
return true;
// Please remember that all code below actually comes
- // from ImplicitReferenceConversion so make sure code remains in sync
+ // from WideningReferenceConversion so make sure code remains in sync
// from any class-type S to any interface-type T.
if (target_type.IsInterface) {
Type target_element_type = TypeManager.GetElementType (target_type);
if (!expr_element_type.IsValueType && !target_element_type.IsValueType)
- if (ImplicitStandardConversionExists (ConstantEC, MyEmptyExpr,
+ if (WideningStandardConversionExists (ConstantEC, MyEmptyExpr,
target_element_type))
return true;
}
// from an array-type to System.Array
if (expr_type.IsArray && (target_type == TypeManager.array_type))
return true;
-
+
+ // from an array-type of type T to IEnumerable<T>
+ if (expr_type.IsArray && TypeManager.IsIEnumerable (expr_type, target_type))
+ return true;
+
// from any delegate type to System.Delegate
if ((expr_type == TypeManager.delegate_type || TypeManager.IsDelegateType (expr_type)) &&
target_type == TypeManager.delegate_type)
/// expr is the expression to convert, returns a new expression of type
/// target_type or null if an implicit conversion is not possible.
/// </summary>
- static public Expression ImplicitNumericConversion (EmitContext ec, Expression expr,
+ static public Expression WideningNumericConversion (EmitContext ec, Expression expr,
Type target_type, Location loc)
{
Type expr_type = expr.Type;
// Attempt to do the implicit constant expression conversions
if (expr is Constant){
+ Expression e;
+
+ e = WideningConstantConversions (target_type, (Constant) expr);
+ if (e != null)
+ return e;
+
if (expr is IntConstant){
- Expression e;
-
- e = TryImplicitIntConversion (target_type, (IntConstant) expr);
+ e = TryWideningIntConversion (target_type, (IntConstant) expr);
if (e != null)
return e;
- } else if (expr is LongConstant && target_type == TypeManager.uint64_type){
- //
- // Try the implicit constant expression conversion
- // from long to ulong, instead of a nice routine,
- // we just inline it
- //
- long v = ((LongConstant) expr).Value;
- if (v >= 0)
- return new ULongConstant ((ulong) v);
}
}
Type real_target_type = target_type;
+ // VB.NET specific: Convert an enum to it's
+ // underlying numeric type or any type that
+ // it's underlyinmg type has widening
+ // conversion to.
+
+ if (expr_type.IsSubclassOf (TypeManager.enum_type)){
+ if (target_type == TypeManager.enum_type ||
+ target_type == TypeManager.object_type) {
+ if (expr is EnumConstant)
+ expr = ((EnumConstant) expr).Child;
+ // We really need all these casts here .... :-(
+ expr = new BoxedCast (new EmptyCast (expr, expr_type));
+ return new EmptyCast (expr, target_type);
+ }
+
+ //
+ // Notice that we have kept the expr_type unmodified, which is only
+ // used later on to
+ if (expr is EnumConstant)
+ expr = ((EnumConstant) expr).Child;
+ else
+ expr = new EmptyCast (expr, TypeManager.EnumToUnderlying (expr_type));
+ expr_type = expr.Type;
+
+ if (expr_type == target_type)
+ return expr;
+ }
+
if (expr_type == TypeManager.sbyte_type){
//
// From sbyte to short, int, long, float, double.
return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
if (real_target_type == TypeManager.double_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+ if (real_target_type == TypeManager.decimal_type)
+ return new ImplicitNew (ec, "System", "Decimal", loc, expr);
} else if (expr_type == TypeManager.short_type){
//
// From short to int, long, float, double
return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
if (real_target_type == TypeManager.float_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+ if (real_target_type == TypeManager.decimal_type)
+ return new ImplicitNew (ec, "System", "Decimal", loc, expr);
} else if (expr_type == TypeManager.ushort_type){
//
// From ushort to int, uint, long, ulong, float, double
return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
if (real_target_type == TypeManager.float_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+ if (real_target_type == TypeManager.decimal_type)
+ return new ImplicitNew (ec, "System", "Decimal", loc, expr);
} else if (expr_type == TypeManager.uint32_type){
//
// From uint to long, ulong, float, double
if (real_target_type == TypeManager.float_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
OpCodes.Conv_R4);
- } else if (expr_type == TypeManager.int64_type){
- //
- // From long/ulong to float, double
- //
- if (real_target_type == TypeManager.double_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
- if (real_target_type == TypeManager.float_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
} else if (expr_type == TypeManager.uint64_type){
//
// From ulong to float, double
if (real_target_type == TypeManager.float_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
OpCodes.Conv_R4);
- } else if (expr_type == TypeManager.char_type){
+ } else if (expr_type == TypeManager.int64_type){
+ //
+ // From long/ulong to float, double
//
- // From char to ushort, int, uint, long, ulong, float, double
- //
- if ((real_target_type == TypeManager.ushort_type) ||
- (real_target_type == TypeManager.int32_type) ||
- (real_target_type == TypeManager.uint32_type))
- return new EmptyCast (expr, target_type);
- if (real_target_type == TypeManager.uint64_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
- if (real_target_type == TypeManager.int64_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
- if (real_target_type == TypeManager.float_type)
- return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
if (real_target_type == TypeManager.double_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+ if (real_target_type == TypeManager.float_type)
+ return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
+ if (real_target_type == TypeManager.decimal_type)
+ return new ImplicitNew (ec, "System", "Decimal", loc, expr);
} else if (expr_type == TypeManager.float_type){
//
// float to double
//
if (real_target_type == TypeManager.double_type)
return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
+ } else if (expr_type == TypeManager.decimal_type){
+ //
+ // From decimal to float, double
+ //
+ if (real_target_type == TypeManager.double_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.double_type, TypeManager.convert_to_double_decimal, expr);
+ if (real_target_type == TypeManager.float_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.float_type, TypeManager.convert_to_single_decimal, expr);
}
return null;
/// <summary>
- /// Same as ImplicitStandardConversionExists except that it also looks at
+ /// Same as WideningStandardConversionExists except that it also looks at
/// implicit user defined conversions - needed for overload resolution
/// </summary>
- public static bool ImplicitConversionExists (EmitContext ec, Expression expr, Type target_type)
+ public static bool WideningConversionExists (EmitContext ec, Expression expr, Type target_type)
{
- if ((expr is NullLiteral) && target_type.IsGenericParameter)
- return TypeParameter_to_Null (target_type);
+ if (expr is NullLiteral) {
+ if (target_type.IsGenericParameter)
+ return TypeParameter_to_Null (target_type);
+
+ if (TypeManager.IsNullableType (target_type))
+ return true;
+ }
- if (ImplicitStandardConversionExists (ec, expr, target_type))
+ if (WideningStandardConversionExists (ec, expr, target_type))
return true;
- Expression dummy = ImplicitUserConversion (ec, expr, target_type, Location.Null);
+ //
+ // VB.NET has no notion of User defined conversions
+ //
- if (dummy != null)
- return true;
+// Expression dummy = ImplicitUserConversion (ec, expr, target_type, Location.Null);
+
+// if (dummy != null)
+// return true;
return false;
}
- public static bool ImplicitUserConversionExists (EmitContext ec, Type source, Type target)
- {
- Expression dummy = ImplicitUserConversion (
- ec, new EmptyExpression (source), target, Location.Null);
- return dummy != null;
- }
+ //
+ // VB.NET has no notion of User defined conversions
+ //
+
+// public static bool ImplicitUserConversionExists (EmitContext ec, Type source, Type target)
+// {
+// Expression dummy = ImplicitUserConversion (
+// ec, new EmptyExpression (source), target, Location.Null);
+// return dummy != null;
+// }
/// <summary>
/// Determines if a standard implicit conversion exists from
///
/// ec should point to a real EmitContext if expr.Type is TypeManager.anonymous_method_type.
/// </summary>
- public static bool ImplicitStandardConversionExists (EmitContext ec, Expression expr, Type target_type)
+ public static bool WideningStandardConversionExists (EmitContext ec, Expression expr, Type target_type)
{
Type expr_type = expr.Type;
}
}
- if (ImplicitReferenceConversionExists (ec, expr, target_type))
+ if (WideningReferenceConversionExists (ec, expr, target_type))
return true;
//
//
// If `expr_type' implements `target_type' (which is an iface)
- // see TryImplicitIntConversion
+ // see TryWideningIntConversion
//
if (target_type.IsInterface && target_type.IsAssignableFrom (expr_type))
return true;
if (target_type == TypeManager.void_ptr_type && expr_type.IsPointer)
return true;
+ if (TypeManager.IsNullableType (expr_type) && TypeManager.IsNullableType (target_type))
+ return true;
+
if (expr_type == TypeManager.anonymous_method_type){
if (!TypeManager.IsDelegateType (target_type))
return false;
continue;
}
- if (ImplicitStandardConversionExists (ec, priv_fmet_param, best))
+ if (WideningStandardConversionExists (ec, priv_fmet_param, best))
best = t;
}
continue;
}
- if (ImplicitStandardConversionExists (ec, priv_fmee_ret, t))
+ if (WideningStandardConversionExists (ec, priv_fmee_ret, t))
best = t;
}
// or encompassed by S to a type encompassing or encompassed by T
//
priv_fms_expr.SetType (param_type);
- if (ImplicitStandardConversionExists (ec, priv_fms_expr, source_type))
+ if (WideningStandardConversionExists (ec, priv_fms_expr, source_type))
src_types_set.Add (param_type);
else {
- if (ImplicitStandardConversionExists (ec, source, param_type))
+ if (WideningStandardConversionExists (ec, source, param_type))
src_types_set.Add (param_type);
}
} else {
//
// Only if S is encompassed by param_type
//
- if (ImplicitStandardConversionExists (ec, source, param_type))
+ if (WideningStandardConversionExists (ec, source, param_type))
src_types_set.Add (param_type);
}
}
ArrayList candidate_set = new ArrayList ();
foreach (Type param_type in src_types_set){
- if (ImplicitStandardConversionExists (ec, source, param_type))
+ if (WideningStandardConversionExists (ec, source, param_type))
candidate_set.Add (param_type);
}
// or encompassed by S to a type encompassing or encompassed by T
//
priv_fms_expr.SetType (ret_type);
- if (ImplicitStandardConversionExists (ec, priv_fms_expr, target))
+ if (WideningStandardConversionExists (ec, priv_fms_expr, target))
tgt_types_set.Add (ret_type);
else {
priv_fms_expr.SetType (target);
- if (ImplicitStandardConversionExists (ec, priv_fms_expr, ret_type))
+ if (WideningStandardConversionExists (ec, priv_fms_expr, ret_type))
tgt_types_set.Add (ret_type);
}
} else {
// Only if T is encompassed by param_type
//
priv_fms_expr.SetType (ret_type);
- if (ImplicitStandardConversionExists (ec, priv_fms_expr, target))
+ if (WideningStandardConversionExists (ec, priv_fms_expr, target))
tgt_types_set.Add (ret_type);
}
}
foreach (Type ret_type in tgt_types_set){
priv_fmt_expr.SetType (ret_type);
- if (ImplicitStandardConversionExists (ec, priv_fmt_expr, target))
+ if (WideningStandardConversionExists (ec, priv_fmt_expr, target))
candidate_set.Add (ret_type);
}
/// <summary>
/// User-defined Implicit conversions
/// </summary>
- static public Expression ImplicitUserConversion (EmitContext ec, Expression source,
- Type target, Location loc)
- {
- return UserDefinedConversion (ec, source, target, loc, false);
- }
+
+ //
+ // VB.NET has no notion of User defined conversions
+ //
+
+// static public Expression ImplicitUserConversion (EmitContext ec, Expression source,
+// Type target, Location loc)
+// {
+// return UserDefinedConversion (ec, source, target, loc, false);
+// }
/// <summary>
/// User-defined Explicit conversions
/// </summary>
- static public Expression ExplicitUserConversion (EmitContext ec, Expression source,
- Type target, Location loc)
- {
- return UserDefinedConversion (ec, source, target, loc, true);
- }
+
+ //
+ // VB.NET has no notion of User defined conversions
+ //
+
+// static public Expression ExplicitUserConversion (EmitContext ec, Expression source,
+// Type target, Location loc)
+// {
+// return UserDefinedConversion (ec, source, target, loc, true);
+// }
static DoubleHash explicit_conv = new DoubleHash (100);
static DoubleHash implicit_conv = new DoubleHash (100);
/// <summary>
/// User-defined conversions
/// </summary>
+
+ //
+ // VB.NET has no notion of User defined conversions. This method is not used.
+ //
static public Expression UserDefinedConversion (EmitContext ec, Expression source,
Type target, Location loc,
bool look_for_explicit)
Type source_type = source.Type;
MethodBase method = null;
+ if (TypeManager.IsNullableType (source_type) && TypeManager.IsNullableType (target))
+ return new Nullable.LiftedConversion (
+ source, target, true, look_for_explicit, loc).Resolve (ec);
+
union = GetConversionOperators (ec, source_type, target, loc, look_for_explicit);
if (union == null)
return null;
// by target.
//
if (look_for_explicit)
- source = ExplicitConversionStandard (ec, source, most_specific_source, loc);
+ source = WideningAndNarrowingConversionStandard (ec, source, most_specific_source, loc);
else
- source = ImplicitConversionStandard (ec, source, most_specific_source, loc);
+ source = WideningConversionStandard (ec, source, most_specific_source, loc);
if (source == null)
return null;
e = new UserCast ((MethodInfo) method, source, loc);
if (e.Type != target){
if (!look_for_explicit)
- e = ImplicitConversionStandard (ec, e, target, loc);
+ e = WideningConversionStandard (ec, e, target, loc);
else
- e = ExplicitConversionStandard (ec, e, target, loc);
+ e = WideningAndNarrowingConversionStandard (ec, e, target, loc);
}
return e;
/// `target_type'. It returns a new expression that can be used
/// in a context that expects a `target_type'.
/// </summary>
- static public Expression ImplicitConversion (EmitContext ec, Expression expr,
+ static public Expression WideningConversion (EmitContext ec, Expression expr,
Type target_type, Location loc)
{
Expression e;
if (target_type == null)
throw new Exception ("Target type is null");
- e = ImplicitConversionStandard (ec, expr, target_type, loc);
+ e = WideningConversionStandard (ec, expr, target_type, loc);
if (e != null)
return e;
- e = ImplicitUserConversion (ec, expr, target_type, loc);
- if (e != null)
- return e;
+ //
+ // VB.NET has no notion of User defined conversions
+ //
+
+// e = ImplicitUserConversion (ec, expr, target_type, loc);
+// if (e != null)
+// return e;
return null;
}
/// that can be used in a context that expects a
/// `target_type'.
///
- /// This is different from `ImplicitConversion' in that the
+ /// This is different from `WideningConversion' in that the
/// user defined implicit conversions are excluded.
/// </summary>
- static public Expression ImplicitConversionStandard (EmitContext ec, Expression expr,
+ static public Expression WideningConversionStandard (EmitContext ec, Expression expr,
Type target_type, Location loc)
{
Type expr_type = expr.Type;
Expression e;
- if ((expr is NullLiteral) && target_type.IsGenericParameter)
- return TypeParameter_to_Null (expr, target_type, loc);
+ if (expr is NullLiteral) {
+ if (target_type.IsGenericParameter)
+ return TypeParameter_to_Null (expr, target_type, loc);
+
+ if (TypeManager.IsNullableType (target_type))
+ return new Nullable.NullableLiteral (target_type, loc);
+ }
+
+ if (TypeManager.IsNullableType (expr_type) && TypeManager.IsNullableType (target_type))
+ return new Nullable.LiftedConversion (
+ expr, target_type, false, false, loc).Resolve (ec);
if (expr.eclass == ExprClass.MethodGroup){
if (!TypeManager.IsDelegateType (target_type)){
if (expr_type.Equals (target_type) && !TypeManager.IsNullType (expr_type))
return expr;
- e = ImplicitNumericConversion (ec, expr, target_type, loc);
+ e = WideningNumericConversion (ec, expr, target_type, loc);
if (e != null)
return e;
- e = ImplicitReferenceConversion (ec, expr, target_type);
+ e = WideningReferenceConversion (ec, expr, target_type);
if (e != null)
return e;
if (errors != Report.Errors)
return new EmptyCast (expr, target_type);
}
+
+ //
+ // VB.NET specific conversions
+ //
+
+ e = WideningStringConversions (ec, expr, target_type, loc);
+ if (e != null)
+ return e;
+
return null;
}
/// into a different data type using casts (See Implicit Constant
/// Expression Conversions)
/// </summary>
- static public Expression TryImplicitIntConversion (Type target_type, IntConstant ic)
+ static public Expression TryWideningIntConversion (Type target_type, IntConstant ic)
{
int value = ic.Value;
- if (target_type == TypeManager.sbyte_type){
- if (value >= SByte.MinValue && value <= SByte.MaxValue)
- return new SByteConstant ((sbyte) value);
- } else if (target_type == TypeManager.byte_type){
- if (value >= Byte.MinValue && value <= Byte.MaxValue)
- return new ByteConstant ((byte) value);
- } else if (target_type == TypeManager.short_type){
- if (value >= Int16.MinValue && value <= Int16.MaxValue)
- return new ShortConstant ((short) value);
- } else if (target_type == TypeManager.ushort_type){
- if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
- return new UShortConstant ((ushort) value);
- } else if (target_type == TypeManager.uint32_type){
- if (value >= 0)
- return new UIntConstant ((uint) value);
- } else if (target_type == TypeManager.uint64_type){
- //
- // we can optimize this case: a positive int32
- // always fits on a uint64. But we need an opcode
- // to do it.
- //
- if (value >= 0)
- return new ULongConstant ((ulong) value);
- } else if (target_type == TypeManager.double_type)
- return new DoubleConstant ((double) value);
- else if (target_type == TypeManager.float_type)
- return new FloatConstant ((float) value);
-
if (value == 0 && ic is IntLiteral && TypeManager.IsEnumType (target_type)){
Type underlying = TypeManager.EnumToUnderlying (target_type);
Constant e = (Constant) ic;
return null;
}
- static public void Error_CannotImplicitConversion (Location loc, Type source, Type target)
+ /// <summary>
+ /// Attempts to perform an implicit constant conversion of the IntConstant
+ /// into a different data type using casts (See Implicit Constant
+ /// Expression Conversions)
+ /// </summary>
+ static public Expression WideningConstantConversions (Type target_type, Constant const_expr)
+ {
+ Constant ret_expr;
+
+ Type const_expr_type = const_expr.Type;
+ Location loc = const_expr.Location;
+
+ if (target_type == TypeManager.byte_type){
+ if (const_expr_type == TypeManager.short_type ||
+ const_expr_type == TypeManager.int32_type ||
+ const_expr_type == TypeManager.int64_type)
+ return const_expr.ToByte (loc);
+ }
+
+ if (target_type == TypeManager.short_type){
+ if (const_expr_type == TypeManager.int32_type ||
+ const_expr_type == TypeManager.int64_type)
+ return const_expr.ToShort (loc);
+ }
+
+ if (target_type == TypeManager.int32_type){
+ if (const_expr_type == TypeManager.int64_type)
+ return const_expr.ToInt (loc);
+ }
+
+ if (target_type == TypeManager.float_type) {
+ if (const_expr_type == TypeManager.double_type)
+ return const_expr.ToDouble (loc);
+ }
+
+ return null;
+ }
+
+ static public Constant NothingToPrimitiveConstants (Expression expr, Type target_type)
+ {
+ NullLiteral null_literal = (NullLiteral) expr;
+ Location loc = null_literal.Location;
+ Type real_target_type = target_type ;
+ Constant retval = null;
+
+ if (null_literal == null)
+ throw new Exception ("FIXME: I was expecting that I would always get only NullLiterals");
+
+ if (target_type.IsSubclassOf(TypeManager.enum_type))
+ real_target_type = TypeManager.EnumToUnderlying (target_type);
+
+ if (real_target_type == TypeManager.bool_type)
+ retval = null_literal.ToBoolean (loc);
+ else if (real_target_type == TypeManager.byte_type)
+ retval = null_literal.ToByte (loc);
+ else if (real_target_type == TypeManager.short_type)
+ retval = null_literal.ToShort (loc);
+ else if (real_target_type == TypeManager.int32_type)
+ retval = null_literal.ToInt (loc);
+ else if (real_target_type == TypeManager.int64_type)
+ null_literal.ToLong (loc);
+ else if (real_target_type == TypeManager.decimal_type)
+ retval = null_literal.ToDecimal (loc);
+ else if (real_target_type == TypeManager.float_type)
+ retval = null_literal.ToLong (loc);
+ else if (real_target_type == TypeManager.double_type)
+ retval = null_literal.ToDouble (loc);
+ else if (real_target_type == TypeManager.char_type)
+ retval = null_literal.ToChar (loc);
+ else if (real_target_type == TypeManager.string_type)
+ retval = new StringConstant (null);
+
+ if (real_target_type != target_type && retval != null)
+ retval = new EnumConstant (retval, target_type);
+
+ return retval;
+ }
+
+ static public void Error_CannotWideningConversion (Location loc, Type source, Type target)
{
if (source.Name == target.Name){
Report.ExtraInformation (loc,
/// <summary>
/// Attempts to implicitly convert `source' into `target_type', using
- /// ImplicitConversion. If there is no implicit conversion, then
+ /// WideningConversion. If there is no implicit conversion, then
/// an error is signaled
/// </summary>
- static public Expression ImplicitConversionRequired (EmitContext ec, Expression source,
+ static public Expression WideningConversionRequired (EmitContext ec, Expression source,
Type target_type, Location loc)
{
Expression e;
int errors = Report.Errors;
- e = ImplicitConversion (ec, source, target_type, loc);
+ e = WideningConversion (ec, source, target_type, loc);
if (Report.Errors > errors)
return null;
if (e != null)
return null;
}
- Error_CannotImplicitConversion (loc, source.Type, target_type);
+ Error_CannotWideningConversion (loc, source.Type, target_type);
return null;
}
/// <summary>
/// Performs the explicit numeric conversions
/// </summary>
- static Expression ExplicitNumericConversion (EmitContext ec, Expression expr, Type target_type, Location loc)
+
+ /// <summary>
+ /// Performs the explicit numeric conversions
+ /// </summary>
+ static Expression NarrowingNumericConversion (EmitContext ec, Expression expr, Type target_type, Location loc)
{
Type expr_type = expr.Type;
if (TypeManager.IsEnumType (real_target_type))
real_target_type = TypeManager.EnumToUnderlying (real_target_type);
- if (ImplicitStandardConversionExists (ec, expr, real_target_type)){
- Expression ce = ImplicitConversionStandard (ec, expr, real_target_type, loc);
+ if (WideningStandardConversionExists (ec, expr, real_target_type)){
+ Expression ce = WideningConversionStandard (ec, expr, real_target_type, loc);
if (real_target_type != target_type)
return new EmptyCast (ce, target_type);
//
if (real_target_type == TypeManager.sbyte_type)
return new ConvCast (ec, expr, target_type, ConvCast.Mode.U1_I1);
- if (real_target_type == TypeManager.char_type)
- return new ConvCast (ec, expr, target_type, ConvCast.Mode.U1_CH);
} else if (expr_type == TypeManager.short_type){
//
- // From short to sbyte, byte, ushort, uint, ulong, char
+ // From short to byte
//
if (real_target_type == TypeManager.sbyte_type)
return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_I1);
return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U4);
if (real_target_type == TypeManager.uint64_type)
return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U8);
- if (real_target_type == TypeManager.char_type)
- return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_CH);
} else if (expr_type == TypeManager.ushort_type){
//
// From ushort to sbyte, byte, short, char
return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_CH);
} else if (expr_type == TypeManager.int32_type){
//
- // From int to sbyte, byte, short, ushort, uint, ulong, char
+ // From int to byte, short
//
if (real_target_type == TypeManager.sbyte_type)
return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_I1);
return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U4);
if (real_target_type == TypeManager.uint64_type)
return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U8);
- if (real_target_type == TypeManager.char_type)
- return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_CH);
} else if (expr_type == TypeManager.uint32_type){
//
// From uint to sbyte, byte, short, ushort, int, char
return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_CH);
} else if (expr_type == TypeManager.int64_type){
//
- // From long to sbyte, byte, short, ushort, int, uint, ulong, char
+ // From long to byte, short, int
//
if (real_target_type == TypeManager.sbyte_type)
return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I1);
return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U4);
if (real_target_type == TypeManager.uint64_type)
return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U8);
- if (real_target_type == TypeManager.char_type)
- return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_CH);
} else if (expr_type == TypeManager.uint64_type){
//
// From ulong to sbyte, byte, short, ushort, int, uint, long, char
return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I8);
if (real_target_type == TypeManager.char_type)
return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_CH);
- } else if (expr_type == TypeManager.char_type){
- //
- // From char to sbyte, byte, short
- //
- if (real_target_type == TypeManager.sbyte_type)
- return new ConvCast (ec, expr, target_type, ConvCast.Mode.CH_I1);
- if (real_target_type == TypeManager.byte_type)
- return new ConvCast (ec, expr, target_type, ConvCast.Mode.CH_U1);
- if (real_target_type == TypeManager.short_type)
- return new ConvCast (ec, expr, target_type, ConvCast.Mode.CH_I2);
} else if (expr_type == TypeManager.float_type){
//
- // From float to sbyte, byte, short,
- // ushort, int, uint, long, ulong, char
- // or decimal
+ // From float to byte, short, int, long, decimal
//
if (real_target_type == TypeManager.sbyte_type)
return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_I1);
if (real_target_type == TypeManager.byte_type)
- return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U1);
+ return new FloatingToFixedCast (ec, expr, target_type, ConvCast.Mode.R8_U1);
if (real_target_type == TypeManager.short_type)
- return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_I2);
+ return new FloatingToFixedCast (ec, expr, target_type, ConvCast.Mode.R8_I2);
if (real_target_type == TypeManager.ushort_type)
return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U2);
if (real_target_type == TypeManager.int32_type)
- return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_I4);
+ return new FloatingToFixedCast (ec, expr, target_type, ConvCast.Mode.R8_I4);
if (real_target_type == TypeManager.uint32_type)
return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U4);
if (real_target_type == TypeManager.int64_type)
- return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_I8);
+ return new FloatingToFixedCast (ec, expr, target_type, ConvCast.Mode.R8_I8);
if (real_target_type == TypeManager.uint64_type)
return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U8);
- if (real_target_type == TypeManager.char_type)
- return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_CH);
+ if (real_target_type == TypeManager.decimal_type)
+ return new ImplicitNew (ec, "System", "Decimal", loc, expr);
} else if (expr_type == TypeManager.double_type){
//
- // From double to byte, byte, short,
- // ushort, int, uint, long, ulong,
- // char, float or decimal
+ // From double to byte, short, int, long, float, decimal
//
if (real_target_type == TypeManager.sbyte_type)
return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_I1);
if (real_target_type == TypeManager.byte_type)
- return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_U1);
+ return new FloatingToFixedCast (ec, expr, target_type, ConvCast.Mode.R8_U1);
if (real_target_type == TypeManager.short_type)
- return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_I2);
+ return new FloatingToFixedCast (ec, expr, target_type, ConvCast.Mode.R8_I2);
if (real_target_type == TypeManager.ushort_type)
return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_U2);
if (real_target_type == TypeManager.int32_type)
return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_I8);
if (real_target_type == TypeManager.uint64_type)
return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_U8);
- if (real_target_type == TypeManager.char_type)
- return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_CH);
+
if (real_target_type == TypeManager.float_type)
return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_R4);
+ if (real_target_type == TypeManager.decimal_type)
+ return new ImplicitNew (ec, "System", "Decimal", loc, expr);
+ } else if (expr_type == TypeManager.decimal_type){
+ //
+ // From decimal to byte, short, int, long
+ //
+ if (real_target_type == TypeManager.byte_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.byte_type, TypeManager.convert_to_byte_decimal, expr);
+ if (real_target_type == TypeManager.short_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.short_type, TypeManager.convert_to_int16_decimal, expr);
+ if (real_target_type == TypeManager.int32_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.int32_type, TypeManager.convert_to_int32_decimal, expr);
+ if (real_target_type == TypeManager.int64_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.int64_type, TypeManager.convert_to_int64_decimal, expr);
}
- // decimal is taken care of by the op_Explicit methods.
+ return null;
+ }
+
+ /// <summary>
+ /// VB.NET specific: Convert to and from boolean
+ /// </summary>
+
+ static public Expression BooleanConversions (EmitContext ec, Expression expr,
+ Type target_type, Location loc)
+ {
+ Type expr_type = expr.Type;
+ Type real_target_type = target_type;
+
+ if (expr_type == TypeManager.bool_type) {
+
+ //
+ // From boolean to byte, short, int,
+ // long, float, double, decimal
+ //
+
+ if (real_target_type == TypeManager.byte_type)
+ return new BooleanToNumericCast (expr, target_type, OpCodes.Conv_U1);
+ if (real_target_type == TypeManager.short_type)
+ return new BooleanToNumericCast (expr, target_type, OpCodes.Conv_I2);
+ if (real_target_type == TypeManager.int32_type)
+ return new BooleanToNumericCast (expr, target_type, OpCodes.Conv_I4);
+ if (real_target_type == TypeManager.int64_type)
+ return new BooleanToNumericCast (expr, target_type, OpCodes.Conv_I8);
+ if (real_target_type == TypeManager.float_type)
+ return new BooleanToNumericCast (expr, target_type, OpCodes.Conv_R4);
+ if (real_target_type == TypeManager.double_type)
+ return new BooleanToNumericCast (expr, target_type, OpCodes.Conv_R8);
+ if (real_target_type == TypeManager.decimal_type) {
+ return new HelperMethodInvocation (ec, expr.Location, TypeManager.decimal_type, TypeManager.msvbcs_decimaltype_from_boolean, expr);
+ }
+ } if (real_target_type == TypeManager.bool_type) {
+
+ //
+ // From byte, short, int, long, float,
+ // double, decimal to boolean
+ //
+
+ if (expr_type == TypeManager.byte_type ||
+ expr_type == TypeManager.short_type ||
+ expr_type == TypeManager.int32_type ||
+ expr_type == TypeManager.int64_type ||
+ expr_type == TypeManager.float_type ||
+ expr_type == TypeManager.double_type)
+ return new NumericToBooleanCast (expr, expr_type);
+ if (expr_type == TypeManager.decimal_type) {
+ return new HelperMethodInvocation (ec, expr.Location, TypeManager.bool_type, TypeManager.convert_to_boolean_decimal, expr);
+ }
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// VB.NET specific: Widening conversions to string
+ /// </summary>
+
+ static public Expression WideningStringConversions (EmitContext ec, Expression expr,
+ Type target_type, Location loc)
+
+ {
+ Type expr_type = expr.Type;
+ Type real_target_type = target_type;
+
+ if (real_target_type == TypeManager.string_type) {
+ //
+ // From char to string
+ //
+ if (expr_type == TypeManager.char_type)
+ return new HelperMethodInvocation (ec, expr.Location, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_char, expr);
+ }
+
+ if(expr_type.IsArray && (expr_type.GetElementType() == TypeManager.char_type)) {
+ //
+ // From char array to string
+ //
+ return new ImplicitNew (ec, "System", "String", loc, expr);
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// VB.NET specific: Narrowing conversions involving strings
+ /// </summary>
+
+ static public Expression NarrowingStringConversions (EmitContext ec, Expression expr,
+ Type target_type, Location loc)
+ {
+ Type expr_type = expr.Type;
+ Type real_target_type = target_type;
+
+ // FIXME: Need to take care of Constants
+
+ if (expr_type == TypeManager.string_type) {
+
+ //
+ // From string to chararray, bool,
+ // byte, short, char, int, long,
+ // float, double, decimal and date
+ //
+
+// if (real_target_type.IsArray && (real_target_type.GetElementType() == TypeManager.char_type))
+// return new HelperMethodInvocation (ec, loc, TypeManager.char_array_type, TypeManager.msvbcs_char_array_type_from_string, loc, expr);
+ if (real_target_type == TypeManager.bool_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.bool_type, TypeManager.msvbcs_booleantype_from_string, expr);
+ if (real_target_type == TypeManager.byte_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.byte_type, TypeManager.msvbcs_bytetype_from_string, expr);
+ if (real_target_type == TypeManager.short_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.short_type, TypeManager.msvbcs_shorttype_from_string, expr);
+ if (real_target_type == TypeManager.char_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.char_type, TypeManager.msvbcs_chartype_from_string, expr);
+ if (real_target_type == TypeManager.int32_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.int32_type, TypeManager.msvbcs_integertype_from_string, expr);
+ if (real_target_type == TypeManager.int64_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.int64_type, TypeManager.msvbcs_longtype_from_string, expr);
+ if (real_target_type == TypeManager.float_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.float_type, TypeManager.msvbcs_singletype_from_string, expr);
+ if (real_target_type == TypeManager.double_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.double_type, TypeManager.msvbcs_doubletype_from_string, expr);
+ if (real_target_type == TypeManager.decimal_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.decimal_type, TypeManager.msvbcs_decimaltype_from_string, expr);
+ if (real_target_type == TypeManager.date_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.date_type, TypeManager.msvbcs_datetype_from_string, expr);
+ } if (real_target_type == TypeManager.string_type) {
+
+ //
+ // From bool, byte, short, char, int,
+ // long, float, double, decimal and
+ // date to string
+ //
+
+ if (expr_type == TypeManager.bool_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_boolean, expr);
+ if (expr_type == TypeManager.byte_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_byte, expr);
+ if (expr_type == TypeManager.short_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_short, expr);
+ if (expr_type == TypeManager.int32_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_integer, expr);
+ if (expr_type == TypeManager.int64_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_long, expr);
+ if (expr_type == TypeManager.float_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_single, expr);
+ if (expr_type == TypeManager.double_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_double, expr);
+ if (expr_type == TypeManager.decimal_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_decimal, expr);
+ if (expr_type == TypeManager.date_type)
+ return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_date, expr);
+ }
+
+ return null;
+ }
+
+
+ /// <summary>
+ /// VB.NET specific: Conversions from Object to Primitive Types
+ /// </summary>
+
+ static public Expression ObjectTypeToPrimitiveTypes (EmitContext ec, Expression expr,
+ Type target_type, Location loc)
+ {
+ Type expr_type = expr.Type;
+ Type real_target_type = target_type;
+ MethodInfo helper_method = null;
+ Expression retexpr;
+
+ if (expr_type != TypeManager.object_type)
+ return null;
+
+ if (target_type.IsSubclassOf (TypeManager.enum_type))
+ real_target_type = TypeManager.EnumToUnderlying (target_type);
+
+
+ if (real_target_type == TypeManager.bool_type)
+ helper_method = TypeManager.msvbcs_booleantype_fromobject_object;
+ if (real_target_type == TypeManager.byte_type)
+ helper_method = TypeManager.msvbcs_bytetype_fromobject_object;
+ if (real_target_type == TypeManager.short_type)
+ helper_method = TypeManager.msvbcs_shorttype_fromobject_object;
+ if (real_target_type == TypeManager.char_type)
+ helper_method = TypeManager.msvbcs_chartype_fromobject_object;
+ if (real_target_type == TypeManager.int32_type)
+ helper_method = TypeManager.msvbcs_integertype_fromobject_object;
+ if (real_target_type == TypeManager.int64_type)
+ helper_method = TypeManager.msvbcs_longtype_fromobject_object;
+ if (real_target_type == TypeManager.float_type)
+ helper_method = TypeManager.msvbcs_singletype_fromobject_object;
+ if (real_target_type == TypeManager.double_type)
+ helper_method = TypeManager.msvbcs_doubletype_fromobject_object;
+ if (real_target_type == TypeManager.decimal_type)
+ helper_method = TypeManager.msvbcs_decimaltype_fromobject_object;
+ if (real_target_type == TypeManager.date_type)
+ helper_method = TypeManager.msvbcs_datetype_fromobject_object;
+ if (real_target_type == TypeManager.string_type)
+ helper_method = TypeManager.msvbcs_stringtype_fromobject_object;
+
+ if (helper_method != null) {
+ retexpr = new HelperMethodInvocation (ec, loc, real_target_type, helper_method, expr);
+ if (target_type != real_target_type)
+ retexpr = new EmptyCast (retexpr, target_type);
+
+ return retexpr;
+ }
return null;
}
+
/// <summary>
/// Returns whether an explicit reference conversion can be performed
/// from source_type to target_type
/// </summary>
- public static bool ExplicitReferenceConversionExists (Type source_type, Type target_type)
+ public static bool NarrowingReferenceConversionExists (Type source_type, Type target_type)
{
bool target_is_type_param = target_type.IsGenericParameter;
bool target_is_value_type = target_type.IsValueType;
if (source_type == target_type)
return true;
+
+ //
+ // From generic parameter to any type
+ //
+ if (source_type.IsGenericParameter)
+ return true;
//
// From object to a generic parameter
Type source_element_type = TypeManager.GetElementType (source_type);
Type target_element_type = TypeManager.GetElementType (target_type);
-
- if (!source_element_type.IsValueType && !target_element_type.IsValueType)
- if (ExplicitReferenceConversionExists (source_element_type,
+
+ if (source_element_type.IsGenericParameter ||
+ (!source_element_type.IsValueType && !target_element_type.IsValueType))
+ if (NarrowingReferenceConversionExists (source_element_type,
target_element_type))
return true;
}
/// <summary>
/// Implements Explicit Reference conversions
/// </summary>
- static Expression ExplicitReferenceConversion (Expression source, Type target_type)
+ static Expression NarrowingReferenceConversion (Expression source, Type target_type)
{
Type source_type = source.Type;
bool target_is_type_param = target_type.IsGenericParameter;
Type target_element_type = TypeManager.GetElementType (target_type);
if (!source_element_type.IsValueType && !target_element_type.IsValueType)
- if (ExplicitReferenceConversionExists (source_element_type,
+ if (NarrowingReferenceConversionExists (source_element_type,
target_element_type))
return new ClassCast (source, target_type);
}
/// Performs an explicit conversion of the expression `expr' whose
/// type is expr.Type to `target_type'.
/// </summary>
- static public Expression ExplicitConversion (EmitContext ec, Expression expr,
+ static public Expression WideningAndNarrowingConversion (EmitContext ec, Expression expr,
Type target_type, Location loc)
{
Type expr_type = expr.Type;
}
int errors = Report.Errors;
- Expression ne = ImplicitConversionStandard (ec, expr, target_type, loc);
+ Expression ne = WideningConversionStandard (ec, expr, target_type, loc);
if (Report.Errors > errors)
return null;
if (ne != null)
return ne;
- ne = ExplicitNumericConversion (ec, expr, target_type, loc);
+ if (TypeManager.IsNullableType (expr.Type) && TypeManager.IsNullableType (target_type))
+ return new Nullable.LiftedConversion (
+ expr, target_type, false, true, loc).Resolve (ec);
+
+ ne = NarrowingNumericConversion (ec, expr, target_type, loc);
if (ne != null)
return ne;
//
// Unboxing conversion.
//
+
+ //
+ // VB.NET treats conversions from object to
+ // the primitive types using the helper
+ // routines in Microsoft.VisualBasic.dll
+ //
+
+ ne = ObjectTypeToPrimitiveTypes(ec, expr, target_type, loc);
+ if (ne != null)
+ return ne;
+
if (expr_type == TypeManager.object_type && target_type.IsValueType)
return new UnboxCast (expr, target_type);
//
- // Skip the ExplicitReferenceConversion because we can not convert
+ // Skip the NarrowingReferenceConversion because we can not convert
// from Null to a ValueType, and ExplicitReference wont check against
// null literal explicitly
//
if (expr_type != TypeManager.null_type){
- ne = ExplicitReferenceConversion (expr, target_type);
+ ne = NarrowingReferenceConversion (expr, target_type);
if (ne != null)
return ne;
}
if (e != null){
Expression ci, ce;
- ci = ImplicitConversionStandard (ec, e, target_type, loc);
+ ci = WideningConversionStandard (ec, e, target_type, loc);
if (ci != null)
return ci;
- ce = ExplicitNumericConversion (ec, e, target_type, loc);
+ ce = NarrowingNumericConversion (ec, e, target_type, loc);
if (ce != null)
return ce;
//
}
}
}
-
- ne = ExplicitUserConversion (ec, expr, target_type, loc);
+
+ //
+ // VB.NET specific conversions
+ //
+
+ ne = BooleanConversions (ec, expr, target_type, loc);
+ if (ne != null)
+ return ne;
+
+ ne = NarrowingStringConversions (ec, expr, target_type, loc);
if (ne != null)
return ne;
+
+
+ //
+ // VB.NET has no notion of User defined conversions
+ //
+
+// ne = ExplicitUserConversion (ec, expr, target_type, loc);
+// if (ne != null)
+// return ne;
if (expr is NullLiteral){
Report.Error (37, loc, "Cannot convert null to value type `" +
}
/// <summary>
- /// Same as ExplicitConversion, only it doesn't include user defined conversions
+ /// Same as WideningAndNarrowingConversion, only it doesn't include user defined conversions
/// </summary>
- static public Expression ExplicitConversionStandard (EmitContext ec, Expression expr,
+ static public Expression WideningAndNarrowingConversionStandard (EmitContext ec, Expression expr,
Type target_type, Location l)
{
int errors = Report.Errors;
- Expression ne = ImplicitConversionStandard (ec, expr, target_type, l);
+ Expression ne = WideningConversionStandard (ec, expr, target_type, l);
if (Report.Errors > errors)
return null;
if (ne != null)
return ne;
- ne = ExplicitNumericConversion (ec, expr, target_type, l);
+ if (TypeManager.IsNullableType (expr.Type) && TypeManager.IsNullableType (target_type))
+ return new Nullable.LiftedConversion (
+ expr, target_type, false, true, l).Resolve (ec);
+
+ ne = NarrowingNumericConversion (ec, expr, target_type, l);
if (ne != null)
return ne;
- ne = ExplicitReferenceConversion (expr, target_type);
+ ne = NarrowingReferenceConversion (expr, target_type);
if (ne != null)
return ne;
Error_CannotConvertType (l, expr.Type, target_type);
return null;
}
+
+ /// <summary>
+ /// Entry point for VB.NET specific implicit conversions
+ /// </summary>
+ static public Expression ImplicitVBConversion (EmitContext ec, Expression expr,
+ Type target_type, Location loc)
+ {
+ if (RootContext.StricterTypeChecking)
+ return WideningConversion (ec, expr, target_type, loc);
+ else
+ return WideningAndNarrowingConversion(ec, expr, target_type, loc);
+ }
+
+ /// <summary>
+ /// Mandates VB.NET specific implicit conversions
+ /// </summary>
+ static public Expression ImplicitVBConversionRequired (EmitContext ec, Expression source,
+ Type target_type, Location loc)
+ {
+ Expression e;
+
+
+ int errors = Report.Errors;
+ e = ImplicitVBConversion (ec, source, target_type, loc);
+ if (Report.Errors > errors)
+ return null;
+ if (e != null)
+ return e;
+
+ if (source is DoubleLiteral) {
+ if (target_type == TypeManager.float_type) {
+ Error_664 (loc, "float", "f");
+ return null;
+ }
+ if (target_type == TypeManager.decimal_type) {
+ Error_664 (loc, "decimal", "m");
+ return null;
+ }
+ }
+
+ if (source is Constant){
+ Constant c = (Constant) source;
+
+ Expression.Error_ConstantValueCannotBeConverted (loc, c.AsString (), target_type);
+ return null;
+ }
+
+ Error_CannotWideningConversion (loc, source.Type, target_type);
+
+ return null;
+ }
+
+ /// <summary>
+ /// Entry point for VB.NET specific explicit conversions
+ /// </summary>
+ static public Expression ExplicitVBConversion (EmitContext ec, Expression expr,
+ Type target_type, Location loc)
+ {
+ return WideningAndNarrowingConversion(ec, expr, target_type, loc);
+ }
+
}
}