* mb-tokenizer.cs: Oops. Also pulled out all of the old
[mono.git] / mcs / mbas / cfold.cs
index 3e8267fca4d27f73cd12978ec228ae2f8de15bb2..e53b71e1ebc27546d8b7cb67ae084b34fd08b331 100644 (file)
@@ -9,7 +9,7 @@
 
 using System;
 
-namespace Mono.CSharp {
+namespace Mono.MonoBASIC {
 
        public class ConstantFold {
 
@@ -195,7 +195,9 @@ namespace Mono.CSharp {
                                if (right is EnumConstant)
                                        right = ((EnumConstant) right).Child;
                        }
-                       
+
+                       Type wrap_as;
+                       Constant result = null;
                        switch (oper){
                        case Binary.Operator.BitwiseOr:
                                DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
@@ -333,7 +335,6 @@ namespace Mono.CSharp {
                                break;
 
                        case Binary.Operator.Addition:
-                               Constant result;
                                bool left_is_string = left is StringConstant;
                                bool right_is_string = right is StringConstant;
 
@@ -342,6 +343,7 @@ namespace Mono.CSharp {
                                // one is a string, and the other is not, then defer
                                // to runtime concatenation
                                //
+                               wrap_as = null;
                                if (left_is_string || right_is_string){
                                        if (left_is_string && right_is_string)
                                                return new StringConstant (
@@ -357,7 +359,6 @@ namespace Mono.CSharp {
                                //
                                // note that E operator + (E x, E y) is invalid
                                //
-                               Type wrap_as = null;
                                if (left is EnumConstant){
                                        if (right is EnumConstant){
                                                return null;
@@ -457,6 +458,29 @@ namespace Mono.CSharp {
                                        return result;
 
                        case Binary.Operator.Subtraction:
+                               //
+                               // handle "E operator - (E x, U y)"
+                               // handle "E operator - (Y y, E x)"
+                               // handle "U operator - (E x, E y)"
+                               //
+                               wrap_as = null;
+                               if (left is EnumConstant){
+                                       if (right is EnumConstant){
+                                               if (left.Type == right.Type)
+                                                       wrap_as = TypeManager.EnumToUnderlying (left.Type);
+                                               else
+                                                       return null;
+                                       }
+                                       if (((EnumConstant) left).Child.Type != right.Type)
+                                               return null;
+
+                                       wrap_as = left.Type;
+                               } else if (right is EnumConstant){
+                                       if (((EnumConstant) right).Child.Type != left.Type)
+                                               return null;
+                                       wrap_as = right.Type;
+                               }
+
                                DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
                                if (left == null || right == null)
                                        return null;
@@ -472,7 +496,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((DoubleConstant) left).Value -
                                                                         ((DoubleConstant) right).Value);
                                                
-                                               return new DoubleConstant (res);
+                                               result = new DoubleConstant (res);
                                        } else if (left is FloatConstant){
                                                float res;
                                                
@@ -483,7 +507,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((FloatConstant) left).Value -
                                                                         ((FloatConstant) right).Value);
                                                
-                                               return new FloatConstant (res);
+                                               result = new FloatConstant (res);
                                        } else if (left is ULongConstant){
                                                ulong res;
                                                
@@ -494,7 +518,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((ULongConstant) left).Value -
                                                                         ((ULongConstant) right).Value);
                                                
-                                               return new ULongConstant (res);
+                                               result = new ULongConstant (res);
                                        } else if (left is LongConstant){
                                                long res;
                                                
@@ -505,7 +529,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((LongConstant) left).Value -
                                                                         ((LongConstant) right).Value);
                                                
-                                               return new LongConstant (res);
+                                               result = new LongConstant (res);
                                        } else if (left is UIntConstant){
                                                uint res;
                                                
@@ -516,7 +540,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((UIntConstant) left).Value -
                                                                         ((UIntConstant) right).Value);
                                                
-                                               return new UIntConstant (res);
+                                               result = new UIntConstant (res);
                                        } else if (left is IntConstant){
                                                int res;
 
@@ -527,14 +551,17 @@ namespace Mono.CSharp {
                                                        res = unchecked (((IntConstant) left).Value -
                                                                         ((IntConstant) right).Value);
 
-                                               return new IntConstant (res);
+                                               result = new IntConstant (res);
                                        } else {
                                                throw new Exception ( "Unexepected input: " + left);
                                        }
                                } catch (OverflowException){
                                        Error_CompileTimeOverflow (loc);
                                }
-                               break;
+                               if (wrap_as != null)
+                                       return new EnumConstant (result, wrap_as);
+                               else
+                                       return result;
                                
                        case Binary.Operator.Multiply:
                                DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);