+ static public Expression NarrowingConversion (EmitContext ec, Expression expr,
+ Type target_type, Location loc)
+ {
+ Type expr_type = expr.Type;
+
+ if (target_type == TypeManager.sbyte_type){
+ //
+ // To sbyte from short, int, long, float, double.
+ //
+ if (expr_type == TypeManager.int32_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_I1);
+ if (expr_type == TypeManager.int64_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I1);
+ if (expr_type == TypeManager.short_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_I1);
+
+ if (expr_type == TypeManager.float_type) {
+ Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
+ return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I1);
+ }
+ if (expr_type == TypeManager.double_type) {
+ Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
+ return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I1);
+ }
+
+ } else if (target_type == TypeManager.byte_type){
+ //
+ // To byte from short, ushort, int, uint, long, ulong, float, double
+ //
+ if (expr_type == TypeManager.short_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U1);
+ if (expr_type == TypeManager.ushort_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_U1);
+ if (expr_type == TypeManager.int32_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U1);
+ if (expr_type == TypeManager.uint32_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_U1);
+ if (expr_type == TypeManager.uint64_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U1);
+ if (expr_type == TypeManager.int64_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U1);
+
+ if (expr_type == TypeManager.float_type) {
+ Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
+ return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U1);
+ }
+ if (expr_type == TypeManager.double_type) {
+ Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
+ return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U1);
+ }
+
+ } else if (target_type == TypeManager.short_type) {
+ //
+ // To short from int, long, float, double
+ //
+ if (expr_type == TypeManager.int32_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_I2);
+ if (expr_type == TypeManager.int64_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I2);
+
+ if (expr_type == TypeManager.float_type) {
+ Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
+ return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I2);
+ }
+ if (expr_type == TypeManager.double_type) {
+ Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
+ return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I2);
+ }
+
+ } else if (target_type == TypeManager.ushort_type) {
+ //
+ // To ushort from int, uint, long, ulong, float, double
+ //
+ if (expr_type == TypeManager.uint32_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_U2);
+ if (expr_type == TypeManager.uint64_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U2);
+ if (expr_type == TypeManager.int32_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U2);
+ if (expr_type == TypeManager.int64_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U2);
+
+ if (expr_type == TypeManager.float_type) {
+ Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
+ return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U2);
+ }
+
+ if (expr_type == TypeManager.double_type) {
+ Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
+ return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U2);
+ }
+
+ } else if (target_type == TypeManager.int32_type){
+ //
+ // To int from long, float, double
+ //
+ if (expr_type == TypeManager.int64_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I4);
+
+ if (expr_type == TypeManager.float_type) {
+ Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
+ return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I4);
+ }
+ if (expr_type == TypeManager.double_type) {
+ Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
+ return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I4);
+ }
+
+ } else if (target_type == TypeManager.uint32_type){
+ //
+ // To uint from long, ulong, float, double
+ //
+ if (expr_type == TypeManager.int64_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U4);
+ if (expr_type == TypeManager.uint64_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I4);
+ if (expr_type == TypeManager.float_type) {
+ Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
+ return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U4);
+ }
+ if (expr_type == TypeManager.double_type) {
+ Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
+ return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U4);
+ }
+
+ } else if (target_type == TypeManager.uint64_type) {
+ //
+ // To long/ulong from float, double
+ //
+ if (expr_type == TypeManager.float_type) {
+ Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
+ return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U8);
+ }
+ if (expr_type == TypeManager.double_type) {
+ Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
+ return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U8);
+ }
+
+ } else if (target_type == TypeManager.int64_type) {
+ //
+ // To long/ulong from float, double
+ //
+ if (expr_type == TypeManager.float_type) {
+ Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
+ return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I8);
+ }
+ if (expr_type == TypeManager.double_type) {
+ Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
+ return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I8);
+ }
+
+ } else if (target_type == TypeManager.char_type){
+ //
+ // To char from ushort, int, uint, long, ulong, float, double
+ //
+ if (expr_type == TypeManager.ushort_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_CH);
+ if (expr_type == TypeManager.int32_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_CH);
+ if (expr_type == TypeManager.uint32_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_CH);
+ if (expr_type == TypeManager.uint64_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_CH);
+ if (expr_type == TypeManager.int64_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_CH);
+
+ if (expr_type == TypeManager.float_type) {
+ Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
+ return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_CH);
+ }
+ if (expr_type == TypeManager.double_type) {
+ Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
+ return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_CH);
+ }
+
+ } else if (target_type == TypeManager.float_type){
+ //
+ // To float from double
+ //
+ if (expr_type == TypeManager.double_type)
+ return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_R4);
+ }
+
+ TypeCode dest_type = Type.GetTypeCode (target_type);
+ TypeCode src_type = Type.GetTypeCode (expr_type);
+ Expression e = null;
+
+ switch (dest_type) {
+ case TypeCode.String:
+ switch (src_type) {
+ case TypeCode.SByte:
+ case TypeCode.Byte:
+ e = RTConversionExpression(ec, "StringType.FromByte", expr, loc);
+ break;
+ case TypeCode.UInt16:
+ case TypeCode.Int16:
+ e = RTConversionExpression(ec, "StringType.FromShort", expr, loc);
+ break;
+ case TypeCode.UInt32:
+ case TypeCode.Int32:
+ e = RTConversionExpression(ec, "StringType.FromInteger", expr, loc);
+ break;
+ case TypeCode.UInt64:
+ case TypeCode.Int64:
+ e = RTConversionExpression(ec, "StringType.FromLong", expr, loc);
+ break;
+ case TypeCode.Char:
+ e = RTConversionExpression(ec, "StringType.FromChar", expr, loc);
+ break;
+ case TypeCode.Single:
+ e = RTConversionExpression(ec, "StringType.FromSingle", expr, loc);
+ break;
+ case TypeCode.Double:
+ e = RTConversionExpression(ec, "StringType.FromDouble", expr, loc);
+ break;
+ case TypeCode.Boolean:
+ e = RTConversionExpression(ec, "StringType.FromBoolean", expr, loc);
+ break;
+ case TypeCode.DateTime:
+ e = RTConversionExpression(ec, "StringType.FromDate", expr, loc);
+ break;
+ case TypeCode.Decimal:
+ e = RTConversionExpression(ec, "StringType.FromDecimal", expr, loc);
+ break;
+ case TypeCode.Object:
+ e = RTConversionExpression(ec, "StringType.FromObject", expr, loc);
+ break;
+ }
+ break;
+
+ case TypeCode.Int32:
+ case TypeCode.UInt32:
+ switch (src_type) {
+ case TypeCode.String:
+ e = RTConversionExpression(ec, "IntegerType.FromString", expr, loc);
+ break;
+ case TypeCode.Object:
+ e = RTConversionExpression(ec, "IntegerType.FromObject", expr, loc);
+ break;
+ }
+ break;
+
+ case TypeCode.Int16:
+ case TypeCode.UInt16:
+ switch (src_type) {
+ case TypeCode.String:
+ e = RTConversionExpression(ec, "ShortType.FromString", expr, loc);
+ break;
+ case TypeCode.Object:
+ e = RTConversionExpression(ec, "ShortType.FromObject", expr, loc);
+ break;
+ }
+ break;
+ case TypeCode.Byte:
+ // Ok, this *is* broken
+ e = RTConversionExpression(ec, "ByteType.FromObject", expr, loc);
+ break;
+ case TypeCode.DateTime:
+ switch (src_type) {
+ case TypeCode.String:
+ e = RTConversionExpression(ec, "DateType.FromString", expr, loc);
+ break;
+ case TypeCode.Object:
+ e = RTConversionExpression(ec, "DateType.FromObject", expr, loc);
+ break;
+ }
+ break;
+ case TypeCode.Char:
+ switch (src_type) {
+
+ case TypeCode.String:
+ e = RTConversionExpression(ec, "CharType.FromString", expr, loc);
+ break;
+
+ }
+ break;
+ }
+
+ // We must examine separately some types that
+ // don't have a TypeCode but are supported
+ // in the runtime
+ if (expr_type == typeof(System.String) && target_type == typeof (System.Char[])) {
+ e = RTConversionExpression(ec, "CharArrayType.FromString", expr, loc);
+ }
+ if (e != null)
+ return e;
+ // VB.NET Objects can be converted to anything by default
+ // unless, that is, an exception at runtime blows it all
+ if (src_type == TypeCode.Object) {
+ Expression cast_type = Mono.MonoBASIC.Parser.DecomposeQI(target_type.ToString(), loc);
+ Cast ce = new Cast (cast_type, expr, loc);
+ ce.IsRuntimeCast = true;
+ return ce.Resolve (ec);
+ }
+ return null;
+ }
+
+ static public Expression ConvertNothingToDefaultValues (EmitContext ec, Expression expr,
+ Type target_type, Location loc)
+ {
+ switch (Type.GetTypeCode (target_type)) {
+ case TypeCode.Boolean :
+ return new BoolConstant (false);
+ case TypeCode.Byte :
+ return new ByteConstant (0);
+ case TypeCode.Char :
+ return new CharConstant ((char)0);
+ case TypeCode.SByte :
+ return new SByteConstant (0);
+ case TypeCode.Int16 :
+ return new ShortConstant (0);
+ case TypeCode.Int32 :
+ return new IntConstant (0);
+ case TypeCode.Int64 :
+ return new LongConstant (0);
+ case TypeCode.Decimal :
+ return new DecimalConstant (System.Decimal.Zero);
+ case TypeCode.Single :
+ return new FloatConstant (0.0F);
+ case TypeCode.Double :
+ return new DoubleConstant (0.0);
+ }
+
+ return null;
+ }
+