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.
// 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 = 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);
}
}
// From decimal to float, double
//
if (real_target_type == TypeManager.double_type)
- return new ImplicitInvocation (ec, "System", "Convert", "ToDouble", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.double_type, TypeManager.convert_to_double_decimal, expr);
if (real_target_type == TypeManager.float_type)
- return new ImplicitInvocation (ec, "System", "Convert" ,"ToSingle", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.float_type, TypeManager.convert_to_single_decimal, expr);
}
return null;
{
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;
}
+ /// <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){
// From decimal to byte, short, int, long
//
if (real_target_type == TypeManager.byte_type)
- return new ImplicitInvocation (ec, "System", "Convert" , "ToByte", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.byte_type, TypeManager.convert_to_byte_decimal, expr);
if (real_target_type == TypeManager.short_type)
- return new ImplicitInvocation (ec, "System", "Convert", "ToInt16", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.short_type, TypeManager.convert_to_int16_decimal, expr);
if (real_target_type == TypeManager.int32_type)
- return new ImplicitInvocation (ec, "System", "Convert", "ToInt32", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.int32_type, TypeManager.convert_to_int32_decimal, expr);
if (real_target_type == TypeManager.int64_type)
- return new ImplicitInvocation (ec, "System", "Convert", "ToInt64", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.int64_type, TypeManager.convert_to_int64_decimal, expr);
}
return null;
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 ImplicitInvocation (ec, "DecimalType", "FromBoolean", loc, expr);
+ return new HelperMethodInvocation (ec, expr.Location, TypeManager.decimal_type, TypeManager.msvbcs_decimaltype_from_boolean, expr);
}
} if (real_target_type == TypeManager.bool_type) {
expr_type == TypeManager.double_type)
return new NumericToBooleanCast (expr, expr_type);
if (expr_type == TypeManager.decimal_type) {
- return new ImplicitInvocation (ec, "System", "Convert", "ToBoolean", loc, expr);
+ return new HelperMethodInvocation (ec, expr.Location, TypeManager.bool_type, TypeManager.convert_to_boolean_decimal, expr);
}
}
// From char to string
//
if (expr_type == TypeManager.char_type)
- return new ImplicitInvocation (ec, "StringType", "FromChar", loc, expr);
+ 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)) {
// float, double, decimal and date
//
- if (real_target_type.IsArray && (real_target_type.GetElementType() == TypeManager.char_type))
- return new ImplicitInvocation (ec, "CharArrayType", "FromString", loc, expr);
+// 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 ImplicitInvocation (ec, "BooleanType", "FromString", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.bool_type, TypeManager.msvbcs_booleantype_from_string, expr);
if (real_target_type == TypeManager.byte_type)
- return new ImplicitInvocation (ec, "ByteType", "FromString", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.byte_type, TypeManager.msvbcs_bytetype_from_string, expr);
if (real_target_type == TypeManager.short_type)
- return new ImplicitInvocation (ec, "ShortType", "FromString", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.short_type, TypeManager.msvbcs_shorttype_from_string, expr);
if (real_target_type == TypeManager.char_type)
- return new ImplicitInvocation (ec, "CharType", "FromString", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.char_type, TypeManager.msvbcs_chartype_from_string, expr);
if (real_target_type == TypeManager.int32_type)
- return new ImplicitInvocation (ec, "IntegerType", "FromString", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.int32_type, TypeManager.msvbcs_integertype_from_string, expr);
if (real_target_type == TypeManager.int64_type)
- return new ImplicitInvocation (ec, "LongType", "FromString", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.int64_type, TypeManager.msvbcs_longtype_from_string, expr);
if (real_target_type == TypeManager.float_type)
- return new ImplicitInvocation (ec, "SingleType", "FromString", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.float_type, TypeManager.msvbcs_singletype_from_string, expr);
if (real_target_type == TypeManager.double_type)
- return new ImplicitInvocation (ec, "DoubleType", "FromString", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.double_type, TypeManager.msvbcs_doubletype_from_string, expr);
if (real_target_type == TypeManager.decimal_type)
- return new ImplicitInvocation (ec, "DecimalType", "FromString", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.decimal_type, TypeManager.msvbcs_decimaltype_from_string, expr);
if (real_target_type == TypeManager.date_type)
- return new ImplicitInvocation (ec, "DateType", "FromString", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.date_type, TypeManager.msvbcs_datetype_from_string, expr);
} if (real_target_type == TypeManager.string_type) {
//
//
if (expr_type == TypeManager.bool_type)
- return new ImplicitInvocation (ec, "StringType", "FromBoolean", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_boolean, expr);
if (expr_type == TypeManager.byte_type)
- return new ImplicitInvocation (ec, "StringType", "FromByte", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_byte, expr);
if (expr_type == TypeManager.short_type)
- return new ImplicitInvocation (ec, "StringType", "FromShort", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_short, expr);
if (expr_type == TypeManager.int32_type)
- return new ImplicitInvocation (ec, "StringType", "FromInteger", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_integer, expr);
if (expr_type == TypeManager.int64_type)
- return new ImplicitInvocation (ec, "StringType", "FromLong", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_long, expr);
if (expr_type == TypeManager.float_type)
- return new ImplicitInvocation (ec, "StringType", "FromSingle", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_single, expr);
if (expr_type == TypeManager.double_type)
- return new ImplicitInvocation (ec, "StringType", "FromDouble", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_double, expr);
if (expr_type == TypeManager.decimal_type)
- return new ImplicitInvocation (ec, "StringType", "FromDecimal", loc, expr);
+ return new HelperMethodInvocation (ec, loc, TypeManager.string_type, TypeManager.msvbcs_stringtype_from_decimal, expr);
if (expr_type == TypeManager.date_type)
- return new ImplicitInvocation (ec, "StringType", "FromDate", loc, expr);
+ 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
//
// 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);