Author: duncan
Date: 2005-05-24 08:21:30 -0400 (Tue, 24 May 2005)
New Revision: 44928
Added:
trunk/mcs/tests/test-386.cs
Modified:
trunk/mcs/mcs/ChangeLog
trunk/mcs/mcs/convert.cs
trunk/mcs/mcs/ecore.cs
trunk/mcs/tests/ChangeLog
trunk/mcs/tests/Makefile
Log:
2005-05-24 Duncan Mak <[EMAIL PROTECTED]>
* ecore.cs (CastFromDecimal): New class for casting a decimal to
another class, used in Convert.ExplicitNumericConversion.
(CastToDecimal): New class, similar to above, but casts to
System.Decimal, used in Convert.ImplicitNumericConversion and also
in explicit convesion from double/float to decimal.
* convert.cs (ImplicitNumericConversion): Handle implicit
conversions to System.Decimal.
(ExplicitNumericConversion): handle explicit conversions to
System.Decimal.
2005-05-24 Duncan Mak <[EMAIL PROTECTED]>
* test-386.cs: New test from #68711.
Modified: trunk/mcs/mcs/ChangeLog
===================================================================
--- trunk/mcs/mcs/ChangeLog 2005-05-24 11:49:23 UTC (rev 44927)
+++ trunk/mcs/mcs/ChangeLog 2005-05-24 12:21:30 UTC (rev 44928)
@@ -1,3 +1,16 @@
+2005-05-24 Duncan Mak <[EMAIL PROTECTED]>
+
+ * ecore.cs (CastFromDecimal): New class for casting a decimal to
+ another class, used in Convert.ExplicitNumericConversion.
+ (CastToDecimal): New class, similar to above, but casts to
+ System.Decimal, used in Convert.ImplicitNumericConversion and also
+ in explicit convesion from double/float to decimal.
+
+ * convert.cs (ImplicitNumericConversion): Handle implicit
+ conversions to System.Decimal.
+ (ExplicitNumericConversion): handle explicit conversions to
+ System.Decimal.
+
2005-05-20 Miguel de Icaza <[EMAIL PROTECTED]>
* typemanager.cs (EnumToUnderlying): Do not throw if we do not
Modified: trunk/mcs/mcs/convert.cs
===================================================================
--- trunk/mcs/mcs/convert.cs 2005-05-24 11:49:23 UTC (rev 44927)
+++ trunk/mcs/mcs/convert.cs 2005-05-24 12:21:30 UTC (rev 44928)
@@ -303,7 +303,7 @@
if (expr_type == TypeManager.sbyte_type){
//
- // From sbyte to short, int, long, float,
double.
+ // From sbyte to short, int, long, float,
double, decimal
//
if (real_target_type == TypeManager.int32_type)
return new OpcodeCast (expr,
target_type, OpCodes.Conv_I4);
@@ -315,9 +315,11 @@
return new OpcodeCast (expr,
target_type, OpCodes.Conv_R4);
if (real_target_type == TypeManager.short_type)
return new OpcodeCast (expr,
target_type, OpCodes.Conv_I2);
+ if (real_target_type ==
TypeManager.decimal_type)
+ return new CastToDecimal (ec, expr);
} else if (expr_type == TypeManager.byte_type){
//
- // From byte to short, ushort, int, uint, long,
ulong, float, double
+ // From byte to short, ushort, int, uint, long,
ulong, float, double, decimal
//
if ((real_target_type ==
TypeManager.short_type) ||
(real_target_type ==
TypeManager.ushort_type) ||
@@ -333,9 +335,12 @@
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 CastToDecimal (ec, expr);
+
} else if (expr_type == TypeManager.short_type){
//
- // From short to int, long, float, double
+ // From short to int, long, float, double,
decimal
//
if (real_target_type == TypeManager.int32_type)
return new EmptyCast (expr,
target_type);
@@ -345,9 +350,12 @@
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 CastToDecimal (ec, expr);
+
} else if (expr_type == TypeManager.ushort_type){
//
- // From ushort to int, uint, long, ulong,
float, double
+ // From ushort to int, uint, long, ulong,
float, double, decimal
//
if (real_target_type == TypeManager.uint32_type)
return new EmptyCast (expr,
target_type);
@@ -362,9 +370,11 @@
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 CastToDecimal (ec, expr);
} else if (expr_type == TypeManager.int32_type){
//
- // From int to long, float, double
+ // From int to long, float, double, decimal
//
if (real_target_type == TypeManager.int64_type)
return new OpcodeCast (expr,
target_type, OpCodes.Conv_I8);
@@ -372,9 +382,11 @@
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 CastToDecimal (ec, expr);
} else if (expr_type == TypeManager.uint32_type){
//
- // From uint to long, ulong, float, double
+ // From uint to long, ulong, float, double,
decimal
//
if (real_target_type == TypeManager.int64_type)
return new OpcodeCast (expr,
target_type, OpCodes.Conv_U8);
@@ -386,6 +398,8 @@
if (real_target_type == TypeManager.float_type)
return new OpcodeCast (expr,
target_type, OpCodes.Conv_R_Un,
OpCodes.Conv_R4);
+ if (real_target_type ==
TypeManager.decimal_type)
+ return new CastToDecimal (ec, expr);
} else if (expr_type == TypeManager.int64_type){
//
// From long/ulong to float, double
@@ -393,7 +407,9 @@
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);
+ return new OpcodeCast (expr,
target_type, OpCodes.Conv_R4);
+ if (real_target_type ==
TypeManager.decimal_type)
+ return new CastToDecimal (ec, expr);
} else if (expr_type == TypeManager.uint64_type){
//
// From ulong to float, double
@@ -403,10 +419,12 @@
OpCodes.Conv_R8);
if (real_target_type == TypeManager.float_type)
return new OpcodeCast (expr,
target_type, OpCodes.Conv_R_Un,
-
OpCodes.Conv_R4);
+ OpCodes.Conv_R4);
+ if (real_target_type ==
TypeManager.decimal_type)
+ return new CastToDecimal (ec, expr);
} else if (expr_type == TypeManager.char_type){
//
- // From char to ushort, int, uint, long, ulong,
float, double
+ // From char to ushort, int, uint, long, ulong,
float, double, decimal
//
if ((real_target_type ==
TypeManager.ushort_type) ||
(real_target_type ==
TypeManager.int32_type) ||
@@ -420,6 +438,8 @@
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 CastToDecimal (ec, expr);
} else if (expr_type == TypeManager.float_type){
//
// float to double
@@ -477,7 +497,7 @@
if (expr_type == TypeManager.sbyte_type){
//
- // From sbyte to short, int, long, float,
double.
+ // From sbyte to short, int, long, float,
double, decimal
//
if ((target_type == TypeManager.int32_type) ||
(target_type == TypeManager.int64_type) ||
@@ -489,7 +509,7 @@
} else if (expr_type == TypeManager.byte_type){
//
- // From byte to short, ushort, int, uint, long,
ulong, float, double
+ // From byte to short, ushort, int, uint, long,
ulong, float, double, decimal
//
if ((target_type == TypeManager.short_type) ||
(target_type == TypeManager.ushort_type) ||
@@ -504,7 +524,7 @@
} else if (expr_type == TypeManager.short_type){
//
- // From short to int, long, float, double
+ // From short to int, long, double, float,
decimal
//
if ((target_type == TypeManager.int32_type) ||
(target_type == TypeManager.int64_type) ||
@@ -515,7 +535,7 @@
} else if (expr_type == TypeManager.ushort_type){
//
- // From ushort to int, uint, long, ulong,
float, double
+ // From ushort to int, uint, long, ulong,
double, float, decimal
//
if ((target_type == TypeManager.uint32_type) ||
(target_type == TypeManager.uint64_type) ||
@@ -528,7 +548,7 @@
} else if (expr_type == TypeManager.int32_type){
//
- // From int to long, float, double
+ // From int to long, double, float, decimal
//
if ((target_type == TypeManager.int64_type) ||
(target_type == TypeManager.double_type) ||
@@ -538,7 +558,7 @@
} else if (expr_type == TypeManager.uint32_type){
//
- // From uint to long, ulong, float, double
+ // From uint to long, ulong, double, float,
decimal
//
if ((target_type == TypeManager.int64_type) ||
(target_type == TypeManager.uint64_type) ||
@@ -550,7 +570,7 @@
} else if ((expr_type == TypeManager.uint64_type) ||
(expr_type == TypeManager.int64_type)) {
//
- // From long/ulong to float, double
+ // From long/ulong to double, float, decimal
//
if ((target_type == TypeManager.double_type) ||
(target_type == TypeManager.float_type) ||
@@ -559,7 +579,7 @@
} else if (expr_type == TypeManager.char_type){
//
- // From char to ushort, int, uint, long, ulong,
float, double
+ // From char to ushort, int, uint, ulong, long,
float, double, decimal
//
if ((target_type == TypeManager.ushort_type) ||
(target_type == TypeManager.int32_type) ||
@@ -1496,9 +1516,11 @@
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 CastToDecimal (ec, expr,
true);
} else if (expr_type == TypeManager.double_type){
//
- // From double to byte, byte, short,
+ // From double to sbyte, byte, short,
// ushort, int, uint, long, ulong,
// char, float or decimal
//
@@ -1522,10 +1544,24 @@
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);
- }
-
- // decimal is taken care of by the op_Explicit methods.
-
+ if (real_target_type ==
TypeManager.decimal_type)
+ return new CastToDecimal (ec, expr,
true);
+ } else if (expr_type == TypeManager.decimal_type) {
+ //
+ // From decimal to short, ushort, int, uint,
+ // long, ulong, char, double or float
+ //
+ if (real_target_type == TypeManager.short_type)
+ if (real_target_type == TypeManager.ushort_type)
+ if (real_target_type == TypeManager.int32_type)
+ if (real_target_type == TypeManager.uint32_type)
+ if (real_target_type == TypeManager.int64_type)
+ if (real_target_type == TypeManager.uint64_type)
+ if (real_target_type == TypeManager.char_type)
+ if (real_target_type == TypeManager.double_type)
+ if (real_target_type == TypeManager.float_type)
+ return new CastFromDecimal (ec, expr,
target_type);
+ }
return null;
}
@@ -1858,7 +1894,7 @@
TypeManager.CSharpName
(target_type) + "'");
return null;
}
-
+
Error_CannotConvertType (loc, original_expr_type,
target_type);
return null;
}
Modified: trunk/mcs/mcs/ecore.cs
===================================================================
--- trunk/mcs/mcs/ecore.cs 2005-05-24 11:49:23 UTC (rev 44927)
+++ trunk/mcs/mcs/ecore.cs 2005-05-24 12:21:30 UTC (rev 44928)
@@ -1382,7 +1382,105 @@
child.Emit (ec);
}
}
+ /// <summary>
+ /// This is a numeric cast to a Decimal
+ /// </summary>
+ public class CastToDecimal : EmptyCast {
+ MethodInfo conversion_operator;
+
+ public CastToDecimal (EmitContext ec, Expression child)
+ : this (ec, child, false)
+ {
+ }
+
+ public CastToDecimal (EmitContext ec, Expression child, bool
find_explicit)
+ : base (child, TypeManager.decimal_type)
+ {
+ conversion_operator = GetConversionOperator (ec,
find_explicit);
+
+ if (conversion_operator == null)
+ Convert.Error_CannotImplicitConversion (loc,
child.Type, type);
+ }
+
+ // Returns the implicit operator that converts from
+ // 'child.Type' to System.Decimal.
+ MethodInfo GetConversionOperator (EmitContext ec, bool
find_explicit)
+ {
+ string operator_name = "op_Implicit";
+
+ if (find_explicit)
+ operator_name = "op_Explicit";
+
+ MethodGroupExpr opers = Expression.MethodLookup (
+ ec, type, operator_name, loc) as
MethodGroupExpr;
+
+ if (opers == null)
+ Convert.Error_CannotImplicitConversion (loc,
child.Type, type);
+
+ foreach (MethodInfo oper in opers.Methods) {
+ ParameterData pd = TypeManager.GetParameterData
(oper);
+
+ if (pd.ParameterType (0) == child.Type &&
oper.ReturnType == type)
+ return oper;
+ }
+
+ return null;
+ }
+ public override void Emit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+ child.Emit (ec);
+
+ ig.Emit (OpCodes.Call, conversion_operator);
+ }
+ }
+ /// <summary>
+ /// This is an explicit numeric cast from a Decimal
+ /// </summary>
+ public class CastFromDecimal : EmptyCast
+ {
+ MethodInfo conversion_operator;
+ public CastFromDecimal (EmitContext ec, Expression child, Type
return_type)
+ : base (child, return_type)
+ {
+ if (child.Type != TypeManager.decimal_type)
+ throw new InternalErrorException (
+ "The expected type is Decimal, instead
it is " + child.Type.FullName);
+
+ conversion_operator = GetConversionOperator (ec);
+ if (conversion_operator == null)
+ Convert.Error_CannotImplicitConversion (loc,
child.Type, type);
+ }
+
+ // Returns the explicit operator that converts from an
+ // express of type System.Decimal to 'type'.
+ MethodInfo GetConversionOperator (EmitContext ec)
+ {
+ MethodGroupExpr opers = Expression.MethodLookup (
+ ec, child.Type, "op_Explicit", loc) as
MethodGroupExpr;
+
+ if (opers == null)
+ Convert.Error_CannotImplicitConversion (loc,
child.Type, type);
+
+ foreach (MethodInfo oper in opers.Methods) {
+ ParameterData pd = TypeManager.GetParameterData
(oper);
+
+ if (pd.ParameterType (0) == child.Type &&
oper.ReturnType == type)
+ return oper;
+ }
+
+ return null;
+ }
+ public override void Emit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+ child.Emit (ec);
+
+ ig.Emit (OpCodes.Call, conversion_operator);
+ }
+ }
+
//
// We need to special case this since an empty cast of
// a NullLiteral is still a Constant
Modified: trunk/mcs/tests/ChangeLog
===================================================================
--- trunk/mcs/tests/ChangeLog 2005-05-24 11:49:23 UTC (rev 44927)
+++ trunk/mcs/tests/ChangeLog 2005-05-24 12:21:30 UTC (rev 44928)
@@ -1,3 +1,7 @@
+2005-05-24 Duncan Mak <[EMAIL PROTECTED]>
+
+ * test-386.cs: New test from #68711.
+
2005-05-20 Martin Baulig <[EMAIL PROTECTED]>
* test-336.cs: Replaced with a working test.
Modified: trunk/mcs/tests/Makefile
===================================================================
--- trunk/mcs/tests/Makefile 2005-05-24 11:49:23 UTC (rev 44927)
+++ trunk/mcs/tests/Makefile 2005-05-24 12:21:30 UTC (rev 44928)
@@ -80,7 +80,7 @@
test-351 test-352 test-353 test-354 test-355 test-356 test-357 test-358
test-359 test-360 \
test-361 test-362 test-363 test-364 test-365 test-366 test-367 test-368
test-369 test-370 \
test-371 test-372 test-373 test-374 test-375 test-376 test-377 test-378
test-379 test-380 \
- test-381 test-382 test-383 test-384 test-385
\
+ test-381 test-382 test-383 test-384 test-385 test-386
\
cls-test-0 cls-test-1 cls-test-2 cls-test-3 cls-test-5 cls-test-6
cls-test-7 cls-test-10 \
cls-test-11 cls-test-12 cls-test-14 cls-test-15 cls-test-16 \
2test-1 2test-2 2test-3 2test-4 2test-5 2test-6 2test-7 2test-8
2test-9 2test-10 \
Added: trunk/mcs/tests/test-386.cs
===================================================================
--- trunk/mcs/tests/test-386.cs 2005-05-24 11:49:23 UTC (rev 44927)
+++ trunk/mcs/tests/test-386.cs 2005-05-24 12:21:30 UTC (rev 44928)
@@ -0,0 +1,21 @@
+using System;
+
+class SuperDecimal{
+ private Decimal val;
+
+ public SuperDecimal (Decimal val)
+ {
+ this.val = val;
+ }
+
+ public static implicit operator SuperDecimal (Decimal val)
+ {
+ return new SuperDecimal (val);
+ }
+
+ public static void Main ()
+ {
+ int i = 2;
+ SuperDecimal sd = i;
+ }
+}
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches