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

Reply via email to