-//\r
-// cfold.cs: Constant Folding\r
-//\r
-// Author:\r
-// Miguel de Icaza (miguel@ximian.com)\r
-//\r
-// (C) 2002 Ximian, Inc.\r
-//\r
-\r
-using System;\r
-\r
-namespace Mono.CSharp {\r
-\r
- public class ConstantFold {\r
-\r
- //\r
- // Performs the numeric promotions on the left and right expresions\r
- // and desposits the results on `lc' and `rc'.\r
- //\r
- // On success, the types of `lc' and `rc' on output will always match,\r
- // and the pair will be one of:\r
- //\r
- // (double, double)\r
- // (float, float)\r
- // (ulong, ulong)\r
- // (long, long)\r
- // (uint, uint)\r
- // (int, int)\r
- //\r
- static void DoConstantNumericPromotions (Binary.Operator oper,\r
- ref Constant left, ref Constant right,\r
- Location loc)\r
- {\r
- if (left is DoubleConstant || right is DoubleConstant){\r
- //\r
- // If either side is a double, convert the other to a double\r
- //\r
- if (!(left is DoubleConstant))\r
- left = left.ToDouble (loc);\r
-\r
- if (!(right is DoubleConstant))\r
- right = right.ToDouble (loc);\r
- return;\r
- } else if (left is FloatConstant || right is FloatConstant) {\r
- //\r
- // If either side is a float, convert the other to a float\r
- //\r
- if (!(left is FloatConstant))\r
- left = left.ToFloat (loc);\r
-\r
- if (!(right is FloatConstant))\r
- right = right.ToFloat (loc);\r
- return;\r
- } else if (left is ULongConstant || right is ULongConstant){\r
- //\r
- // If either operand is of type ulong, the other operand is\r
- // converted to type ulong. or an error ocurrs if the other\r
- // operand is of type sbyte, short, int or long\r
- //\r
- Constant match, other;\r
- \r
- if (left is ULongConstant){\r
- other = right;\r
- match = left;\r
- if (!(right is ULongConstant))\r
- right = right.ToULong (loc);\r
- } else {\r
- other = left;\r
- match = right;\r
- left = left.ToULong (loc);\r
- }\r
-\r
-#if WRONG\r
- if (other is SByteConstant || other is ShortConstant ||\r
- other is IntConstant || other is LongConstant){\r
- Binary.Error_OperatorAmbiguous\r
- (loc, oper, other.Type, match.Type);\r
- left = null;\r
- right = null;\r
- }\r
-#endif\r
- return;\r
- } else if (left is LongConstant || right is LongConstant){\r
- //\r
- // If either operand is of type long, the other operand is converted\r
- // to type long.\r
- //\r
- if (!(left is LongConstant))\r
- left = left.ToLong (loc);\r
- else if (!(right is LongConstant))\r
- right = right.ToLong (loc);\r
- return;\r
- } else if (left is UIntConstant || right is UIntConstant){\r
- //\r
- // If either operand is of type uint, and the other\r
- // operand is of type sbyte, short or int, othe operands are\r
- // converted to type long.\r
- //\r
- if (!(left is UIntConstant))\r
- left = left.ToUInt (loc);\r
- else if (!(right is UIntConstant))\r
- right = right.ToUInt (loc);\r
- return;\r
- } else {\r
- //\r
- // Force conversions to int32\r
- //\r
- if (!(left is IntConstant))\r
- left = left.ToInt (loc);\r
- if (!(right is IntConstant))\r
- right = right.ToInt (loc);\r
- }\r
- return;\r
- }\r
-\r
- static void Error_CompileTimeOverflow (Location loc)\r
- {\r
- Report.Error (220, loc, "The operation overflows at compile time in checked mode");\r
- }\r
- \r
- /// <summary>\r
- /// Constant expression folder for binary operations.\r
- ///\r
- /// Returns null if the expression can not be folded.\r
- /// </summary>\r
- static public Expression BinaryFold (EmitContext ec, Binary.Operator oper,\r
- Constant left, Constant right, Location loc)\r
- {\r
- Type lt = left.Type;\r
- Type rt = right.Type;\r
- Type result_type = null;\r
- bool bool_res;\r
- \r
- //\r
- // Enumerator folding\r
- //\r
- if (rt == lt && left is EnumConstant)\r
- result_type = lt;\r
-\r
- switch (oper){\r
- case Binary.Operator.BitwiseOr:\r
- DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
- if (left == null || right == null)\r
- return null;\r
- \r
- if (left is IntConstant){\r
- IntConstant v;\r
- int res = ((IntConstant) left).Value | ((IntConstant) right).Value;\r
- \r
- v = new IntConstant (res);\r
- if (result_type == null)\r
- return v;\r
- else\r
- return new EnumConstant (v, result_type);\r
- } else if (left is UIntConstant){\r
- UIntConstant v;\r
- uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value;\r
- \r
- v = new UIntConstant (res);\r
- if (result_type == null)\r
- return v;\r
- else\r
- return new EnumConstant (v, result_type);\r
- } else if (left is LongConstant){\r
- LongConstant v;\r
- long res = ((LongConstant)left).Value | ((LongConstant)right).Value;\r
- \r
- v = new LongConstant (res);\r
- if (result_type == null)\r
- return v;\r
- else\r
- return new EnumConstant (v, result_type);\r
- } else if (left is ULongConstant){\r
- ULongConstant v;\r
- ulong res = ((ULongConstant)left).Value |\r
- ((ULongConstant)right).Value;\r
- \r
- v = new ULongConstant (res);\r
- if (result_type == null)\r
- return v;\r
- else\r
- return new EnumConstant (v, result_type);\r
- }\r
- break;\r
- \r
- case Binary.Operator.BitwiseAnd:\r
- DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
- if (left == null || right == null)\r
- return null;\r
- \r
- if (left is IntConstant){\r
- IntConstant v;\r
- int res = ((IntConstant) left).Value & ((IntConstant) right).Value;\r
- \r
- v = new IntConstant (res);\r
- if (result_type == null)\r
- return v;\r
- else\r
- return new EnumConstant (v, result_type);\r
- } else if (left is UIntConstant){\r
- UIntConstant v;\r
- uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value;\r
- \r
- v = new UIntConstant (res);\r
- if (result_type == null)\r
- return v;\r
- else\r
- return new EnumConstant (v, result_type);\r
- } else if (left is LongConstant){\r
- LongConstant v;\r
- long res = ((LongConstant)left).Value & ((LongConstant)right).Value;\r
- \r
- v = new LongConstant (res);\r
- if (result_type == null)\r
- return v;\r
- else\r
- return new EnumConstant (v, result_type);\r
- } else if (left is ULongConstant){\r
- ULongConstant v;\r
- ulong res = ((ULongConstant)left).Value &\r
- ((ULongConstant)right).Value;\r
- \r
- v = new ULongConstant (res);\r
- if (result_type == null)\r
- return v;\r
- else\r
- return new EnumConstant (v, result_type);\r
- }\r
- break;\r
-\r
- case Binary.Operator.ExclusiveOr:\r
- DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
- if (left == null || right == null)\r
- return null;\r
- \r
- if (left is IntConstant){\r
- IntConstant v;\r
- int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value;\r
- \r
- v = new IntConstant (res);\r
- if (result_type == null)\r
- return v;\r
- else\r
- return new EnumConstant (v, result_type);\r
- } else if (left is UIntConstant){\r
- UIntConstant v;\r
- uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value;\r
- \r
- v = new UIntConstant (res);\r
- if (result_type == null)\r
- return v;\r
- else\r
- return new EnumConstant (v, result_type);\r
- } else if (left is LongConstant){\r
- LongConstant v;\r
- long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value;\r
- \r
- v = new LongConstant (res);\r
- if (result_type == null)\r
- return v;\r
- else\r
- return new EnumConstant (v, result_type);\r
- } else if (left is ULongConstant){\r
- ULongConstant v;\r
- ulong res = ((ULongConstant)left).Value ^\r
- ((ULongConstant)right).Value;\r
- \r
- v = new ULongConstant (res);\r
- if (result_type == null)\r
- return v;\r
- else\r
- return new EnumConstant (v, result_type);\r
- }\r
- break;\r
-\r
- case Binary.Operator.Addition:\r
- bool left_is_string = left is StringConstant;\r
- bool right_is_string = right is StringConstant;\r
-\r
- //\r
- // If both sides are strings, then concatenate, if\r
- // one is a string, and the other is not, then defer\r
- // to runtime concatenation\r
- //\r
- if (left_is_string || right_is_string){\r
- if (left_is_string && right_is_string)\r
- return new StringConstant (\r
- ((StringConstant) left).Value +\r
- ((StringConstant) right).Value);\r
- \r
- return null;\r
- }\r
-\r
- DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
- if (left == null || right == null)\r
- return null;\r
-\r
- try {\r
- if (left is DoubleConstant){\r
- double res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((DoubleConstant) left).Value +\r
- ((DoubleConstant) right).Value);\r
- else\r
- res = unchecked (((DoubleConstant) left).Value +\r
- ((DoubleConstant) right).Value);\r
- \r
- return new DoubleConstant (res);\r
- } else if (left is FloatConstant){\r
- float res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((FloatConstant) left).Value +\r
- ((FloatConstant) right).Value);\r
- else\r
- res = unchecked (((FloatConstant) left).Value +\r
- ((FloatConstant) right).Value);\r
- \r
- return new FloatConstant (res);\r
- } else if (left is ULongConstant){\r
- ulong res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((ULongConstant) left).Value +\r
- ((ULongConstant) right).Value);\r
- else\r
- res = unchecked (((ULongConstant) left).Value +\r
- ((ULongConstant) right).Value);\r
- \r
- return new ULongConstant (res);\r
- } else if (left is LongConstant){\r
- long res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((LongConstant) left).Value +\r
- ((LongConstant) right).Value);\r
- else\r
- res = unchecked (((LongConstant) left).Value +\r
- ((LongConstant) right).Value);\r
- \r
- return new LongConstant (res);\r
- } else if (left is UIntConstant){\r
- uint res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((UIntConstant) left).Value +\r
- ((UIntConstant) right).Value);\r
- else\r
- res = unchecked (((UIntConstant) left).Value +\r
- ((UIntConstant) right).Value);\r
- \r
- return new UIntConstant (res);\r
- } else if (left is IntConstant){\r
- int res;\r
-\r
- if (ec.ConstantCheckState)\r
- res = checked (((IntConstant) left).Value +\r
- ((IntConstant) right).Value);\r
- else\r
- res = unchecked (((IntConstant) left).Value +\r
- ((IntConstant) right).Value);\r
-\r
- return new IntConstant (res);\r
- } else {\r
- throw new Exception ( "Unexepected input: " + left);\r
- }\r
- } catch (OverflowException){\r
- Error_CompileTimeOverflow (loc);\r
- }\r
- break;\r
-\r
- case Binary.Operator.Subtraction:\r
- DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
- if (left == null || right == null)\r
- return null;\r
-\r
- try {\r
- if (left is DoubleConstant){\r
- double res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((DoubleConstant) left).Value -\r
- ((DoubleConstant) right).Value);\r
- else\r
- res = unchecked (((DoubleConstant) left).Value -\r
- ((DoubleConstant) right).Value);\r
- \r
- return new DoubleConstant (res);\r
- } else if (left is FloatConstant){\r
- float res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((FloatConstant) left).Value -\r
- ((FloatConstant) right).Value);\r
- else\r
- res = unchecked (((FloatConstant) left).Value -\r
- ((FloatConstant) right).Value);\r
- \r
- return new FloatConstant (res);\r
- } else if (left is ULongConstant){\r
- ulong res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((ULongConstant) left).Value -\r
- ((ULongConstant) right).Value);\r
- else\r
- res = unchecked (((ULongConstant) left).Value -\r
- ((ULongConstant) right).Value);\r
- \r
- return new ULongConstant (res);\r
- } else if (left is LongConstant){\r
- long res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((LongConstant) left).Value -\r
- ((LongConstant) right).Value);\r
- else\r
- res = unchecked (((LongConstant) left).Value -\r
- ((LongConstant) right).Value);\r
- \r
- return new LongConstant (res);\r
- } else if (left is UIntConstant){\r
- uint res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((UIntConstant) left).Value -\r
- ((UIntConstant) right).Value);\r
- else\r
- res = unchecked (((UIntConstant) left).Value -\r
- ((UIntConstant) right).Value);\r
- \r
- return new UIntConstant (res);\r
- } else if (left is IntConstant){\r
- int res;\r
-\r
- if (ec.ConstantCheckState)\r
- res = checked (((IntConstant) left).Value -\r
- ((IntConstant) right).Value);\r
- else\r
- res = unchecked (((IntConstant) left).Value -\r
- ((IntConstant) right).Value);\r
-\r
- return new IntConstant (res);\r
- } else {\r
- throw new Exception ( "Unexepected input: " + left);\r
- }\r
- } catch (OverflowException){\r
- Error_CompileTimeOverflow (loc);\r
- }\r
- break;\r
- \r
- case Binary.Operator.Multiply:\r
- DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
- if (left == null || right == null)\r
- return null;\r
-\r
- try {\r
- if (left is DoubleConstant){\r
- double res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((DoubleConstant) left).Value *\r
- ((DoubleConstant) right).Value);\r
- else\r
- res = unchecked (((DoubleConstant) left).Value *\r
- ((DoubleConstant) right).Value);\r
- \r
- return new DoubleConstant (res);\r
- } else if (left is FloatConstant){\r
- float res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((FloatConstant) left).Value *\r
- ((FloatConstant) right).Value);\r
- else\r
- res = unchecked (((FloatConstant) left).Value *\r
- ((FloatConstant) right).Value);\r
- \r
- return new FloatConstant (res);\r
- } else if (left is ULongConstant){\r
- ulong res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((ULongConstant) left).Value *\r
- ((ULongConstant) right).Value);\r
- else\r
- res = unchecked (((ULongConstant) left).Value *\r
- ((ULongConstant) right).Value);\r
- \r
- return new ULongConstant (res);\r
- } else if (left is LongConstant){\r
- long res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((LongConstant) left).Value *\r
- ((LongConstant) right).Value);\r
- else\r
- res = unchecked (((LongConstant) left).Value *\r
- ((LongConstant) right).Value);\r
- \r
- return new LongConstant (res);\r
- } else if (left is UIntConstant){\r
- uint res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((UIntConstant) left).Value *\r
- ((UIntConstant) right).Value);\r
- else\r
- res = unchecked (((UIntConstant) left).Value *\r
- ((UIntConstant) right).Value);\r
- \r
- return new UIntConstant (res);\r
- } else if (left is IntConstant){\r
- int res;\r
-\r
- if (ec.ConstantCheckState)\r
- res = checked (((IntConstant) left).Value *\r
- ((IntConstant) right).Value);\r
- else\r
- res = unchecked (((IntConstant) left).Value *\r
- ((IntConstant) right).Value);\r
-\r
- return new IntConstant (res);\r
- } else {\r
- throw new Exception ( "Unexepected input: " + left);\r
- }\r
- } catch (OverflowException){\r
- Error_CompileTimeOverflow (loc);\r
- }\r
- break;\r
-\r
- case Binary.Operator.Division:\r
- DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
- if (left == null || right == null)\r
- return null;\r
-\r
- try {\r
- if (left is DoubleConstant){\r
- double res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((DoubleConstant) left).Value /\r
- ((DoubleConstant) right).Value);\r
- else\r
- res = unchecked (((DoubleConstant) left).Value /\r
- ((DoubleConstant) right).Value);\r
- \r
- return new DoubleConstant (res);\r
- } else if (left is FloatConstant){\r
- float res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((FloatConstant) left).Value /\r
- ((FloatConstant) right).Value);\r
- else\r
- res = unchecked (((FloatConstant) left).Value /\r
- ((FloatConstant) right).Value);\r
- \r
- return new FloatConstant (res);\r
- } else if (left is ULongConstant){\r
- ulong res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((ULongConstant) left).Value /\r
- ((ULongConstant) right).Value);\r
- else\r
- res = unchecked (((ULongConstant) left).Value /\r
- ((ULongConstant) right).Value);\r
- \r
- return new ULongConstant (res);\r
- } else if (left is LongConstant){\r
- long res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((LongConstant) left).Value /\r
- ((LongConstant) right).Value);\r
- else\r
- res = unchecked (((LongConstant) left).Value /\r
- ((LongConstant) right).Value);\r
- \r
- return new LongConstant (res);\r
- } else if (left is UIntConstant){\r
- uint res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((UIntConstant) left).Value /\r
- ((UIntConstant) right).Value);\r
- else\r
- res = unchecked (((UIntConstant) left).Value /\r
- ((UIntConstant) right).Value);\r
- \r
- return new UIntConstant (res);\r
- } else if (left is IntConstant){\r
- int res;\r
-\r
- if (ec.ConstantCheckState)\r
- res = checked (((IntConstant) left).Value /\r
- ((IntConstant) right).Value);\r
- else\r
- res = unchecked (((IntConstant) left).Value /\r
- ((IntConstant) right).Value);\r
-\r
- return new IntConstant (res);\r
- } else {\r
- throw new Exception ( "Unexepected input: " + left);\r
- }\r
- } catch (OverflowException){\r
- Error_CompileTimeOverflow (loc);\r
- }\r
- break;\r
- \r
- case Binary.Operator.Modulus:\r
- DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
- if (left == null || right == null)\r
- return null;\r
-\r
- try {\r
- if (left is DoubleConstant){\r
- double res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((DoubleConstant) left).Value %\r
- ((DoubleConstant) right).Value);\r
- else\r
- res = unchecked (((DoubleConstant) left).Value %\r
- ((DoubleConstant) right).Value);\r
- \r
- return new DoubleConstant (res);\r
- } else if (left is FloatConstant){\r
- float res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((FloatConstant) left).Value %\r
- ((FloatConstant) right).Value);\r
- else\r
- res = unchecked (((FloatConstant) left).Value %\r
- ((FloatConstant) right).Value);\r
- \r
- return new FloatConstant (res);\r
- } else if (left is ULongConstant){\r
- ulong res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((ULongConstant) left).Value %\r
- ((ULongConstant) right).Value);\r
- else\r
- res = unchecked (((ULongConstant) left).Value %\r
- ((ULongConstant) right).Value);\r
- \r
- return new ULongConstant (res);\r
- } else if (left is LongConstant){\r
- long res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((LongConstant) left).Value %\r
- ((LongConstant) right).Value);\r
- else\r
- res = unchecked (((LongConstant) left).Value %\r
- ((LongConstant) right).Value);\r
- \r
- return new LongConstant (res);\r
- } else if (left is UIntConstant){\r
- uint res;\r
- \r
- if (ec.ConstantCheckState)\r
- res = checked (((UIntConstant) left).Value %\r
- ((UIntConstant) right).Value);\r
- else\r
- res = unchecked (((UIntConstant) left).Value %\r
- ((UIntConstant) right).Value);\r
- \r
- return new UIntConstant (res);\r
- } else if (left is IntConstant){\r
- int res;\r
-\r
- if (ec.ConstantCheckState)\r
- res = checked (((IntConstant) left).Value %\r
- ((IntConstant) right).Value);\r
- else\r
- res = unchecked (((IntConstant) left).Value %\r
- ((IntConstant) right).Value);\r
-\r
- return new IntConstant (res);\r
- } else {\r
- throw new Exception ( "Unexepected input: " + left);\r
- }\r
- } catch (OverflowException){\r
- Error_CompileTimeOverflow (loc);\r
- }\r
- break;\r
-\r
- //\r
- // There is no overflow checking on left shift\r
- //\r
- case Binary.Operator.LeftShift:\r
- IntConstant ic = right.ToInt (loc);\r
- if (ic == null){\r
- Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);\r
- return null;\r
- }\r
- int lshift_val = ic.Value;\r
-\r
- IntConstant lic;\r
- if ((lic = left.ConvertToInt ()) != null)\r
- return new IntConstant (lic.Value << lshift_val);\r
-\r
- UIntConstant luic;\r
- if ((luic = left.ConvertToUInt ()) != null)\r
- return new UIntConstant (luic.Value << lshift_val);\r
-\r
- LongConstant llc;\r
- if ((llc = left.ConvertToLong ()) != null)\r
- return new LongConstant (llc.Value << lshift_val);\r
-\r
- ULongConstant lulc;\r
- if ((lulc = left.ConvertToULong ()) != null)\r
- return new ULongConstant (lulc.Value << lshift_val);\r
-\r
- Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);\r
- break;\r
-\r
- //\r
- // There is no overflow checking on right shift\r
- //\r
- case Binary.Operator.RightShift:\r
- IntConstant sic = right.ToInt (loc);\r
- if (sic == null){\r
- Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);\r
- return null;\r
- }\r
- int rshift_val = sic.Value;\r
-\r
- IntConstant ric;\r
- if ((ric = left.ConvertToInt ()) != null)\r
- return new IntConstant (ric.Value >> rshift_val);\r
-\r
- UIntConstant ruic;\r
- if ((ruic = left.ConvertToUInt ()) != null)\r
- return new UIntConstant (ruic.Value >> rshift_val);\r
-\r
- LongConstant rlc;\r
- if ((rlc = left.ConvertToLong ()) != null)\r
- return new LongConstant (rlc.Value >> rshift_val);\r
-\r
- ULongConstant rulc;\r
- if ((rulc = left.ConvertToULong ()) != null)\r
- return new ULongConstant (rulc.Value >> rshift_val);\r
-\r
- Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);\r
- break;\r
-\r
- case Binary.Operator.LogicalAnd:\r
- if (left is BoolConstant && right is BoolConstant){\r
- return new BoolConstant (\r
- ((BoolConstant) left).Value &&\r
- ((BoolConstant) right).Value);\r
- }\r
- break;\r
-\r
- case Binary.Operator.LogicalOr:\r
- if (left is BoolConstant && right is BoolConstant){\r
- return new BoolConstant (\r
- ((BoolConstant) left).Value ||\r
- ((BoolConstant) right).Value);\r
- }\r
- break;\r
- \r
- case Binary.Operator.Equality:\r
- if (left is BoolConstant && right is BoolConstant){\r
- return new BoolConstant (\r
- ((BoolConstant) left).Value ==\r
- ((BoolConstant) right).Value);\r
- \r
- }\r
- if (left is StringConstant && right is StringConstant){\r
- return new BoolConstant (\r
- ((StringConstant) left).Value ==\r
- ((StringConstant) right).Value);\r
- \r
- }\r
- \r
- DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
- if (left == null || right == null)\r
- return null;\r
-\r
- bool_res = false;\r
- if (left is DoubleConstant)\r
- bool_res = ((DoubleConstant) left).Value ==\r
- ((DoubleConstant) right).Value;\r
- else if (left is FloatConstant)\r
- bool_res = ((FloatConstant) left).Value ==\r
- ((FloatConstant) right).Value;\r
- else if (left is ULongConstant)\r
- bool_res = ((ULongConstant) left).Value ==\r
- ((ULongConstant) right).Value;\r
- else if (left is LongConstant)\r
- bool_res = ((LongConstant) left).Value ==\r
- ((LongConstant) right).Value;\r
- else if (left is UIntConstant)\r
- bool_res = ((UIntConstant) left).Value ==\r
- ((UIntConstant) right).Value;\r
- else if (left is IntConstant)\r
- bool_res = ((IntConstant) left).Value ==\r
- ((IntConstant) right).Value;\r
- else\r
- return null;\r
-\r
- return new BoolConstant (bool_res);\r
-\r
- case Binary.Operator.Inequality:\r
- if (left is BoolConstant && right is BoolConstant){\r
- return new BoolConstant (\r
- ((BoolConstant) left).Value !=\r
- ((BoolConstant) right).Value);\r
- }\r
- if (left is StringConstant && right is StringConstant){\r
- return new BoolConstant (\r
- ((StringConstant) left).Value !=\r
- ((StringConstant) right).Value);\r
- \r
- }\r
- DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
- if (left == null || right == null)\r
- return null;\r
-\r
- bool_res = false;\r
- if (left is DoubleConstant)\r
- bool_res = ((DoubleConstant) left).Value !=\r
- ((DoubleConstant) right).Value;\r
- else if (left is FloatConstant)\r
- bool_res = ((FloatConstant) left).Value !=\r
- ((FloatConstant) right).Value;\r
- else if (left is ULongConstant)\r
- bool_res = ((ULongConstant) left).Value !=\r
- ((ULongConstant) right).Value;\r
- else if (left is LongConstant)\r
- bool_res = ((LongConstant) left).Value !=\r
- ((LongConstant) right).Value;\r
- else if (left is UIntConstant)\r
- bool_res = ((UIntConstant) left).Value !=\r
- ((UIntConstant) right).Value;\r
- else if (left is IntConstant)\r
- bool_res = ((IntConstant) left).Value !=\r
- ((IntConstant) right).Value;\r
- else\r
- return null;\r
-\r
- return new BoolConstant (bool_res);\r
-\r
- case Binary.Operator.LessThan:\r
- DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
- if (left == null || right == null)\r
- return null;\r
-\r
- bool_res = false;\r
- if (left is DoubleConstant)\r
- bool_res = ((DoubleConstant) left).Value <\r
- ((DoubleConstant) right).Value;\r
- else if (left is FloatConstant)\r
- bool_res = ((FloatConstant) left).Value <\r
- ((FloatConstant) right).Value;\r
- else if (left is ULongConstant)\r
- bool_res = ((ULongConstant) left).Value <\r
- ((ULongConstant) right).Value;\r
- else if (left is LongConstant)\r
- bool_res = ((LongConstant) left).Value <\r
- ((LongConstant) right).Value;\r
- else if (left is UIntConstant)\r
- bool_res = ((UIntConstant) left).Value <\r
- ((UIntConstant) right).Value;\r
- else if (left is IntConstant)\r
- bool_res = ((IntConstant) left).Value <\r
- ((IntConstant) right).Value;\r
- else\r
- return null;\r
-\r
- return new BoolConstant (bool_res);\r
- \r
- case Binary.Operator.GreaterThan:\r
- DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
- if (left == null || right == null)\r
- return null;\r
-\r
- bool_res = false;\r
- if (left is DoubleConstant)\r
- bool_res = ((DoubleConstant) left).Value >\r
- ((DoubleConstant) right).Value;\r
- else if (left is FloatConstant)\r
- bool_res = ((FloatConstant) left).Value >\r
- ((FloatConstant) right).Value;\r
- else if (left is ULongConstant)\r
- bool_res = ((ULongConstant) left).Value >\r
- ((ULongConstant) right).Value;\r
- else if (left is LongConstant)\r
- bool_res = ((LongConstant) left).Value >\r
- ((LongConstant) right).Value;\r
- else if (left is UIntConstant)\r
- bool_res = ((UIntConstant) left).Value >\r
- ((UIntConstant) right).Value;\r
- else if (left is IntConstant)\r
- bool_res = ((IntConstant) left).Value >\r
- ((IntConstant) right).Value;\r
- else\r
- return null;\r
-\r
- return new BoolConstant (bool_res);\r
-\r
- case Binary.Operator.GreaterThanOrEqual:\r
- DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
- if (left == null || right == null)\r
- return null;\r
-\r
- bool_res = false;\r
- if (left is DoubleConstant)\r
- bool_res = ((DoubleConstant) left).Value >=\r
- ((DoubleConstant) right).Value;\r
- else if (left is FloatConstant)\r
- bool_res = ((FloatConstant) left).Value >=\r
- ((FloatConstant) right).Value;\r
- else if (left is ULongConstant)\r
- bool_res = ((ULongConstant) left).Value >=\r
- ((ULongConstant) right).Value;\r
- else if (left is LongConstant)\r
- bool_res = ((LongConstant) left).Value >=\r
- ((LongConstant) right).Value;\r
- else if (left is UIntConstant)\r
- bool_res = ((UIntConstant) left).Value >=\r
- ((UIntConstant) right).Value;\r
- else if (left is IntConstant)\r
- bool_res = ((IntConstant) left).Value >=\r
- ((IntConstant) right).Value;\r
- else\r
- return null;\r
-\r
- return new BoolConstant (bool_res);\r
-\r
- case Binary.Operator.LessThanOrEqual:\r
- DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
- if (left == null || right == null)\r
- return null;\r
-\r
- bool_res = false;\r
- if (left is DoubleConstant)\r
- bool_res = ((DoubleConstant) left).Value <=\r
- ((DoubleConstant) right).Value;\r
- else if (left is FloatConstant)\r
- bool_res = ((FloatConstant) left).Value <=\r
- ((FloatConstant) right).Value;\r
- else if (left is ULongConstant)\r
- bool_res = ((ULongConstant) left).Value <=\r
- ((ULongConstant) right).Value;\r
- else if (left is LongConstant)\r
- bool_res = ((LongConstant) left).Value <=\r
- ((LongConstant) right).Value;\r
- else if (left is UIntConstant)\r
- bool_res = ((UIntConstant) left).Value <=\r
- ((UIntConstant) right).Value;\r
- else if (left is IntConstant)\r
- bool_res = ((IntConstant) left).Value <=\r
- ((IntConstant) right).Value;\r
- else\r
- return null;\r
-\r
- return new BoolConstant (bool_res);\r
- }\r
- \r
- return null;\r
- }\r
- }\r
-}\r
+//
+// cfold.cs: Constant Folding
+//
+// Author:
+// Miguel de Icaza (miguel@ximian.com)
+//
+// (C) 2002 Ximian, Inc.
+//
+
+using System;
+
+namespace Mono.MonoBASIC {
+
+ public class ConstantFold {
+
+ //
+ // Performs the numeric promotions on the left and right expresions
+ // and desposits the results on `lc' and `rc'.
+ //
+ // On success, the types of `lc' and `rc' on output will always match,
+ // and the pair will be one of:
+ //
+ // (double, double)
+ // (float, float)
+ // (ulong, ulong)
+ // (long, long)
+ // (uint, uint)
+ // (int, int)
+ //
+ static void DoConstantNumericPromotions (EmitContext ec, Binary.Operator oper,
+ ref Constant left, ref Constant right,
+ Location loc)
+ {
+ if (left is DoubleConstant || right is DoubleConstant){
+ //
+ // If either side is a double, convert the other to a double
+ //
+ if (!(left is DoubleConstant))
+ left = left.ToDouble (loc);
+
+ if (!(right is DoubleConstant))
+ right = right.ToDouble (loc);
+ return;
+ } else if (left is FloatConstant || right is FloatConstant) {
+ //
+ // If either side is a float, convert the other to a float
+ //
+ if (!(left is FloatConstant))
+ left = left.ToFloat (loc);
+
+ if (!(right is FloatConstant))
+ right = right.ToFloat (loc);
+; return;
+ } else if (left is ULongConstant || right is ULongConstant){
+ //
+ // If either operand is of type ulong, the other operand is
+ // converted to type ulong. or an error ocurrs if the other
+ // operand is of type sbyte, short, int or long
+ //
+ Constant match, other;
+
+ if (left is ULongConstant){
+ other = right;
+ match = left;
+ if (!(right is ULongConstant))
+ right = right.ToULong (loc);
+ } else {
+ other = left;
+ match = right;
+ left = left.ToULong (loc);
+ }
+
+#if WRONG
+ if (other is SByteConstant || other is ShortConstant ||
+ other is IntConstant || other is LongConstant){
+ Binary.Error_OperatorAmbiguous
+ (loc, oper, other.Type, match.Type);
+ left = null;
+ right = null;
+ }
+#endif
+ return;
+ } else if (left is LongConstant || right is LongConstant){
+ //
+ // If either operand is of type long, the other operand is converted
+ // to type long.
+ //
+ if (!(left is LongConstant))
+ left = left.ToLong (loc);
+ else if (!(right is LongConstant))
+ right = right.ToLong (loc);
+ return;
+ } else if (left is UIntConstant || right is UIntConstant){
+ //
+ // If either operand is of type uint, and the other
+ // operand is of type sbyte, short or int, the operands are
+ // converted to type long.
+ //
+ Constant match, other;
+ if (left is UIntConstant){
+ other = right;
+ match = left;
+ } else {
+ other = left;
+ match = right;
+ }
+
+ // Nothing to do.
+ if (other is UIntConstant)
+ return;
+
+ if (other is SByteConstant || other is ShortConstant ||
+ other is IntConstant){
+ left = left.ToLong (loc);
+ right = right.ToLong (loc);
+ }
+
+ return;
+ } else if (left is EnumConstant || right is EnumConstant){
+ //
+ // If either operand is an enum constant, the other one must
+ // be implicitly convertable to that enum's underlying type.
+ //
+ EnumConstant match;
+ Constant other;
+ if (left is EnumConstant){
+ other = right;
+ match = (EnumConstant) left;
+ } else {
+ other = left;
+ match = (EnumConstant) right;
+ }
+
+ bool need_check = (other is EnumConstant) ||
+ ((oper != Binary.Operator.Addition) &&
+ (oper != Binary.Operator.Subtraction));
+
+ if (need_check &&
+ !Expression.ImplicitConversionExists (ec, match, other.Type)) {
+ Expression.Error_CannotConvertImplicit (loc, match.Type, other.Type);
+ left = null;
+ right = null;
+ return;
+ }
+
+ if (left is EnumConstant)
+ left = ((EnumConstant) left).Child;
+ if (right is EnumConstant)
+ right = ((EnumConstant) right).Child;
+ return;
+
+ } else {
+ //
+ // Force conversions to int32
+ //
+ if (!(left is IntConstant))
+ left = left.ToInt (loc);
+ if (!(right is IntConstant))
+ right = right.ToInt (loc);
+ }
+ return;
+ }
+
+ static void Error_CompileTimeOverflow (Location loc)
+ {
+ Report.Error (220, loc, "The operation overflows at compile time in checked mode");
+ }
+
+ /// <summary>
+ /// Constant expression folder for binary operations.
+ ///
+ /// Returns null if the expression can not be folded.
+ /// </summary>
+ static public Expression BinaryFold (EmitContext ec, Binary.Operator oper,
+ Constant left, Constant right, Location loc)
+ {
+ Type lt = left.Type;
+ Type rt = right.Type;
+ Type result_type = null;
+ bool bool_res;
+
+ //
+ // Enumerator folding
+ //
+ if (rt == lt && left is EnumConstant)
+ result_type = lt;
+
+ //
+ // During an enum evaluation, we need to unwrap enumerations
+ //
+ if (ec.InEnumContext){
+ if (left is EnumConstant)
+ left = ((EnumConstant) left).Child;
+
+ 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);
+ if (left == null || right == null)
+ return null;
+
+ if (left is IntConstant){
+ IntConstant v;
+ int res = ((IntConstant) left).Value | ((IntConstant) right).Value;
+
+ v = new IntConstant (res);
+ if (result_type == null)
+ return v;
+ else
+ return new EnumConstant (v, result_type);
+ } else if (left is UIntConstant){
+ UIntConstant v;
+ uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value;
+
+ v = new UIntConstant (res);
+ if (result_type == null)
+ return v;
+ else
+ return new EnumConstant (v, result_type);
+ } else if (left is LongConstant){
+ LongConstant v;
+ long res = ((LongConstant)left).Value | ((LongConstant)right).Value;
+
+ v = new LongConstant (res);
+ if (result_type == null)
+ return v;
+ else
+ return new EnumConstant (v, result_type);
+ } else if (left is ULongConstant){
+ ULongConstant v;
+ ulong res = ((ULongConstant)left).Value |
+ ((ULongConstant)right).Value;
+
+ v = new ULongConstant (res);
+ if (result_type == null)
+ return v;
+ else
+ return new EnumConstant (v, result_type);
+ }
+ break;
+
+ case Binary.Operator.BitwiseAnd:
+ DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+ if (left == null || right == null)
+ return null;
+
+ if (left is IntConstant){
+ IntConstant v;
+ int res = ((IntConstant) left).Value & ((IntConstant) right).Value;
+
+ v = new IntConstant (res);
+ if (result_type == null)
+ return v;
+ else
+ return new EnumConstant (v, result_type);
+ } else if (left is UIntConstant){
+ UIntConstant v;
+ uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value;
+
+ v = new UIntConstant (res);
+ if (result_type == null)
+ return v;
+ else
+ return new EnumConstant (v, result_type);
+ } else if (left is LongConstant){
+ LongConstant v;
+ long res = ((LongConstant)left).Value & ((LongConstant)right).Value;
+
+ v = new LongConstant (res);
+ if (result_type == null)
+ return v;
+ else
+ return new EnumConstant (v, result_type);
+ } else if (left is ULongConstant){
+ ULongConstant v;
+ ulong res = ((ULongConstant)left).Value &
+ ((ULongConstant)right).Value;
+
+ v = new ULongConstant (res);
+ if (result_type == null)
+ return v;
+ else
+ return new EnumConstant (v, result_type);
+ }
+ break;
+
+ case Binary.Operator.ExclusiveOr:
+ DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+ if (left == null || right == null)
+ return null;
+
+ if (left is IntConstant){
+ IntConstant v;
+ int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value;
+
+ v = new IntConstant (res);
+ if (result_type == null)
+ return v;
+ else
+ return new EnumConstant (v, result_type);
+ } else if (left is UIntConstant){
+ UIntConstant v;
+ uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value;
+
+ v = new UIntConstant (res);
+ if (result_type == null)
+ return v;
+ else
+ return new EnumConstant (v, result_type);
+ } else if (left is LongConstant){
+ LongConstant v;
+ long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value;
+
+ v = new LongConstant (res);
+ if (result_type == null)
+ return v;
+ else
+ return new EnumConstant (v, result_type);
+ } else if (left is ULongConstant){
+ ULongConstant v;
+ ulong res = ((ULongConstant)left).Value ^
+ ((ULongConstant)right).Value;
+
+ v = new ULongConstant (res);
+ if (result_type == null)
+ return v;
+ else
+ return new EnumConstant (v, result_type);
+ }
+ break;
+
+ case Binary.Operator.Addition:
+ bool left_is_string = left is StringConstant;
+ bool right_is_string = right is StringConstant;
+
+ //
+ // If both sides are strings, then concatenate, if
+ // 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 (
+ ((StringConstant) left).Value +
+ ((StringConstant) right).Value);
+
+ return null;
+ }
+
+ //
+ // handle "E operator + (E x, U y)"
+ // handle "E operator + (Y y, E x)"
+ //
+ // note that E operator + (E x, E y) is invalid
+ //
+ if (left is EnumConstant){
+ if (right is EnumConstant){
+ 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;
+ }
+
+ result = null;
+ DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+ if (left == null || right == null)
+ return null;
+
+ try {
+ if (left is DoubleConstant){
+ double res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((DoubleConstant) left).Value +
+ ((DoubleConstant) right).Value);
+ else
+ res = unchecked (((DoubleConstant) left).Value +
+ ((DoubleConstant) right).Value);
+
+ result = new DoubleConstant (res);
+ } else if (left is FloatConstant){
+ float res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((FloatConstant) left).Value +
+ ((FloatConstant) right).Value);
+ else
+ res = unchecked (((FloatConstant) left).Value +
+ ((FloatConstant) right).Value);
+
+ result = new FloatConstant (res);
+ } else if (left is ULongConstant){
+ ulong res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((ULongConstant) left).Value +
+ ((ULongConstant) right).Value);
+ else
+ res = unchecked (((ULongConstant) left).Value +
+ ((ULongConstant) right).Value);
+
+ result = new ULongConstant (res);
+ } else if (left is LongConstant){
+ long res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((LongConstant) left).Value +
+ ((LongConstant) right).Value);
+ else
+ res = unchecked (((LongConstant) left).Value +
+ ((LongConstant) right).Value);
+
+ result = new LongConstant (res);
+ } else if (left is UIntConstant){
+ uint res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((UIntConstant) left).Value +
+ ((UIntConstant) right).Value);
+ else
+ res = unchecked (((UIntConstant) left).Value +
+ ((UIntConstant) right).Value);
+
+ result = new UIntConstant (res);
+ } else if (left is IntConstant){
+ int res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((IntConstant) left).Value +
+ ((IntConstant) right).Value);
+ else
+ res = unchecked (((IntConstant) left).Value +
+ ((IntConstant) right).Value);
+
+ result = new IntConstant (res);
+ } else {
+ throw new Exception ( "Unexepected input: " + left);
+ }
+ } catch (OverflowException){
+ Error_CompileTimeOverflow (loc);
+ }
+
+ if (wrap_as != null)
+ return new EnumConstant (result, wrap_as);
+ else
+ 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;
+
+ try {
+ if (left is DoubleConstant){
+ double res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((DoubleConstant) left).Value -
+ ((DoubleConstant) right).Value);
+ else
+ res = unchecked (((DoubleConstant) left).Value -
+ ((DoubleConstant) right).Value);
+
+ result = new DoubleConstant (res);
+ } else if (left is FloatConstant){
+ float res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((FloatConstant) left).Value -
+ ((FloatConstant) right).Value);
+ else
+ res = unchecked (((FloatConstant) left).Value -
+ ((FloatConstant) right).Value);
+
+ result = new FloatConstant (res);
+ } else if (left is ULongConstant){
+ ulong res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((ULongConstant) left).Value -
+ ((ULongConstant) right).Value);
+ else
+ res = unchecked (((ULongConstant) left).Value -
+ ((ULongConstant) right).Value);
+
+ result = new ULongConstant (res);
+ } else if (left is LongConstant){
+ long res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((LongConstant) left).Value -
+ ((LongConstant) right).Value);
+ else
+ res = unchecked (((LongConstant) left).Value -
+ ((LongConstant) right).Value);
+
+ result = new LongConstant (res);
+ } else if (left is UIntConstant){
+ uint res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((UIntConstant) left).Value -
+ ((UIntConstant) right).Value);
+ else
+ res = unchecked (((UIntConstant) left).Value -
+ ((UIntConstant) right).Value);
+
+ result = new UIntConstant (res);
+ } else if (left is IntConstant){
+ int res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((IntConstant) left).Value -
+ ((IntConstant) right).Value);
+ else
+ res = unchecked (((IntConstant) left).Value -
+ ((IntConstant) right).Value);
+
+ result = new IntConstant (res);
+ } else {
+ throw new Exception ( "Unexepected input: " + left);
+ }
+ } catch (OverflowException){
+ Error_CompileTimeOverflow (loc);
+ }
+ 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);
+ if (left == null || right == null)
+ return null;
+
+ try {
+ if (left is DoubleConstant){
+ double res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((DoubleConstant) left).Value *
+ ((DoubleConstant) right).Value);
+ else
+ res = unchecked (((DoubleConstant) left).Value *
+ ((DoubleConstant) right).Value);
+
+ return new DoubleConstant (res);
+ } else if (left is FloatConstant){
+ float res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((FloatConstant) left).Value *
+ ((FloatConstant) right).Value);
+ else
+ res = unchecked (((FloatConstant) left).Value *
+ ((FloatConstant) right).Value);
+
+ return new FloatConstant (res);
+ } else if (left is ULongConstant){
+ ulong res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((ULongConstant) left).Value *
+ ((ULongConstant) right).Value);
+ else
+ res = unchecked (((ULongConstant) left).Value *
+ ((ULongConstant) right).Value);
+
+ return new ULongConstant (res);
+ } else if (left is LongConstant){
+ long res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((LongConstant) left).Value *
+ ((LongConstant) right).Value);
+ else
+ res = unchecked (((LongConstant) left).Value *
+ ((LongConstant) right).Value);
+
+ return new LongConstant (res);
+ } else if (left is UIntConstant){
+ uint res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((UIntConstant) left).Value *
+ ((UIntConstant) right).Value);
+ else
+ res = unchecked (((UIntConstant) left).Value *
+ ((UIntConstant) right).Value);
+
+ return new UIntConstant (res);
+ } else if (left is IntConstant){
+ int res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((IntConstant) left).Value *
+ ((IntConstant) right).Value);
+ else
+ res = unchecked (((IntConstant) left).Value *
+ ((IntConstant) right).Value);
+
+ return new IntConstant (res);
+ } else {
+ throw new Exception ( "Unexepected input: " + left);
+ }
+ } catch (OverflowException){
+ Error_CompileTimeOverflow (loc);
+ }
+ break;
+
+ case Binary.Operator.Division:
+ DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+ if (left == null || right == null)
+ return null;
+
+ try {
+ if (left is DoubleConstant){
+ double res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((DoubleConstant) left).Value /
+ ((DoubleConstant) right).Value);
+ else
+ res = unchecked (((DoubleConstant) left).Value /
+ ((DoubleConstant) right).Value);
+
+ return new DoubleConstant (res);
+ } else if (left is FloatConstant){
+ float res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((FloatConstant) left).Value /
+ ((FloatConstant) right).Value);
+ else
+ res = unchecked (((FloatConstant) left).Value /
+ ((FloatConstant) right).Value);
+
+ return new FloatConstant (res);
+ } else if (left is ULongConstant){
+ ulong res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((ULongConstant) left).Value /
+ ((ULongConstant) right).Value);
+ else
+ res = unchecked (((ULongConstant) left).Value /
+ ((ULongConstant) right).Value);
+
+ return new ULongConstant (res);
+ } else if (left is LongConstant){
+ long res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((LongConstant) left).Value /
+ ((LongConstant) right).Value);
+ else
+ res = unchecked (((LongConstant) left).Value /
+ ((LongConstant) right).Value);
+
+ return new LongConstant (res);
+ } else if (left is UIntConstant){
+ uint res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((UIntConstant) left).Value /
+ ((UIntConstant) right).Value);
+ else
+ res = unchecked (((UIntConstant) left).Value /
+ ((UIntConstant) right).Value);
+
+ return new UIntConstant (res);
+ } else if (left is IntConstant){
+ int res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((IntConstant) left).Value /
+ ((IntConstant) right).Value);
+ else
+ res = unchecked (((IntConstant) left).Value /
+ ((IntConstant) right).Value);
+
+ return new IntConstant (res);
+ } else {
+ throw new Exception ( "Unexepected input: " + left);
+ }
+ } catch (OverflowException){
+ Error_CompileTimeOverflow (loc);
+
+ } catch (DivideByZeroException) {
+ Report.Error (020, loc, "Division by constant zero");
+ }
+
+ break;
+
+ case Binary.Operator.Modulus:
+ DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+ if (left == null || right == null)
+ return null;
+
+ try {
+ if (left is DoubleConstant){
+ double res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((DoubleConstant) left).Value %
+ ((DoubleConstant) right).Value);
+ else
+ res = unchecked (((DoubleConstant) left).Value %
+ ((DoubleConstant) right).Value);
+
+ return new DoubleConstant (res);
+ } else if (left is FloatConstant){
+ float res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((FloatConstant) left).Value %
+ ((FloatConstant) right).Value);
+ else
+ res = unchecked (((FloatConstant) left).Value %
+ ((FloatConstant) right).Value);
+
+ return new FloatConstant (res);
+ } else if (left is ULongConstant){
+ ulong res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((ULongConstant) left).Value %
+ ((ULongConstant) right).Value);
+ else
+ res = unchecked (((ULongConstant) left).Value %
+ ((ULongConstant) right).Value);
+
+ return new ULongConstant (res);
+ } else if (left is LongConstant){
+ long res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((LongConstant) left).Value %
+ ((LongConstant) right).Value);
+ else
+ res = unchecked (((LongConstant) left).Value %
+ ((LongConstant) right).Value);
+
+ return new LongConstant (res);
+ } else if (left is UIntConstant){
+ uint res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((UIntConstant) left).Value %
+ ((UIntConstant) right).Value);
+ else
+ res = unchecked (((UIntConstant) left).Value %
+ ((UIntConstant) right).Value);
+
+ return new UIntConstant (res);
+ } else if (left is IntConstant){
+ int res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((IntConstant) left).Value %
+ ((IntConstant) right).Value);
+ else
+ res = unchecked (((IntConstant) left).Value %
+ ((IntConstant) right).Value);
+
+ return new IntConstant (res);
+ } else {
+ throw new Exception ( "Unexepected input: " + left);
+ }
+ } catch (OverflowException){
+ Error_CompileTimeOverflow (loc);
+ }
+ break;
+
+ //
+ // There is no overflow checking on left shift
+ //
+ case Binary.Operator.LeftShift:
+ IntConstant ic = right.ToInt (loc);
+ if (ic == null){
+ Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
+ return null;
+ }
+ int lshift_val = ic.Value;
+
+ IntConstant lic;
+ if ((lic = left.ConvertToInt ()) != null)
+ return new IntConstant (lic.Value << lshift_val);
+
+ UIntConstant luic;
+ if ((luic = left.ConvertToUInt ()) != null)
+ return new UIntConstant (luic.Value << lshift_val);
+
+ LongConstant llc;
+ if ((llc = left.ConvertToLong ()) != null)
+ return new LongConstant (llc.Value << lshift_val);
+
+ ULongConstant lulc;
+ if ((lulc = left.ConvertToULong ()) != null)
+ return new ULongConstant (lulc.Value << lshift_val);
+
+ Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
+ break;
+
+ //
+ // There is no overflow checking on right shift
+ //
+ case Binary.Operator.RightShift:
+ IntConstant sic = right.ToInt (loc);
+ if (sic == null){
+ Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
+ return null;
+ }
+ int rshift_val = sic.Value;
+
+ IntConstant ric;
+ if ((ric = left.ConvertToInt ()) != null)
+ return new IntConstant (ric.Value >> rshift_val);
+
+ UIntConstant ruic;
+ if ((ruic = left.ConvertToUInt ()) != null)
+ return new UIntConstant (ruic.Value >> rshift_val);
+
+ LongConstant rlc;
+ if ((rlc = left.ConvertToLong ()) != null)
+ return new LongConstant (rlc.Value >> rshift_val);
+
+ ULongConstant rulc;
+ if ((rulc = left.ConvertToULong ()) != null)
+ return new ULongConstant (rulc.Value >> rshift_val);
+
+ Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
+ break;
+
+ case Binary.Operator.LogicalAnd:
+ if (left is BoolConstant && right is BoolConstant){
+ return new BoolConstant (
+ ((BoolConstant) left).Value &&
+ ((BoolConstant) right).Value);
+ }
+ break;
+
+ case Binary.Operator.LogicalOr:
+ if (left is BoolConstant && right is BoolConstant){
+ return new BoolConstant (
+ ((BoolConstant) left).Value ||
+ ((BoolConstant) right).Value);
+ }
+ break;
+
+ case Binary.Operator.Equality:
+ if (left is BoolConstant && right is BoolConstant){
+ return new BoolConstant (
+ ((BoolConstant) left).Value ==
+ ((BoolConstant) right).Value);
+
+ }
+ if (left is StringConstant && right is StringConstant){
+ return new BoolConstant (
+ ((StringConstant) left).Value ==
+ ((StringConstant) right).Value);
+
+ }
+
+ DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+ if (left == null || right == null)
+ return null;
+
+ bool_res = false;
+ if (left is DoubleConstant)
+ bool_res = ((DoubleConstant) left).Value ==
+ ((DoubleConstant) right).Value;
+ else if (left is FloatConstant)
+ bool_res = ((FloatConstant) left).Value ==
+ ((FloatConstant) right).Value;
+ else if (left is ULongConstant)
+ bool_res = ((ULongConstant) left).Value ==
+ ((ULongConstant) right).Value;
+ else if (left is LongConstant)
+ bool_res = ((LongConstant) left).Value ==
+ ((LongConstant) right).Value;
+ else if (left is UIntConstant)
+ bool_res = ((UIntConstant) left).Value ==
+ ((UIntConstant) right).Value;
+ else if (left is IntConstant)
+ bool_res = ((IntConstant) left).Value ==
+ ((IntConstant) right).Value;
+ else
+ return null;
+
+ return new BoolConstant (bool_res);
+
+ case Binary.Operator.Inequality:
+ if (left is BoolConstant && right is BoolConstant){
+ return new BoolConstant (
+ ((BoolConstant) left).Value !=
+ ((BoolConstant) right).Value);
+ }
+ if (left is StringConstant && right is StringConstant){
+ return new BoolConstant (
+ ((StringConstant) left).Value !=
+ ((StringConstant) right).Value);
+
+ }
+ DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+ if (left == null || right == null)
+ return null;
+
+ bool_res = false;
+ if (left is DoubleConstant)
+ bool_res = ((DoubleConstant) left).Value !=
+ ((DoubleConstant) right).Value;
+ else if (left is FloatConstant)
+ bool_res = ((FloatConstant) left).Value !=
+ ((FloatConstant) right).Value;
+ else if (left is ULongConstant)
+ bool_res = ((ULongConstant) left).Value !=
+ ((ULongConstant) right).Value;
+ else if (left is LongConstant)
+ bool_res = ((LongConstant) left).Value !=
+ ((LongConstant) right).Value;
+ else if (left is UIntConstant)
+ bool_res = ((UIntConstant) left).Value !=
+ ((UIntConstant) right).Value;
+ else if (left is IntConstant)
+ bool_res = ((IntConstant) left).Value !=
+ ((IntConstant) right).Value;
+ else
+ return null;
+
+ return new BoolConstant (bool_res);
+
+ case Binary.Operator.LessThan:
+ DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+ if (left == null || right == null)
+ return null;
+
+ bool_res = false;
+ if (left is DoubleConstant)
+ bool_res = ((DoubleConstant) left).Value <
+ ((DoubleConstant) right).Value;
+ else if (left is FloatConstant)
+ bool_res = ((FloatConstant) left).Value <
+ ((FloatConstant) right).Value;
+ else if (left is ULongConstant)
+ bool_res = ((ULongConstant) left).Value <
+ ((ULongConstant) right).Value;
+ else if (left is LongConstant)
+ bool_res = ((LongConstant) left).Value <
+ ((LongConstant) right).Value;
+ else if (left is UIntConstant)
+ bool_res = ((UIntConstant) left).Value <
+ ((UIntConstant) right).Value;
+ else if (left is IntConstant)
+ bool_res = ((IntConstant) left).Value <
+ ((IntConstant) right).Value;
+ else
+ return null;
+
+ return new BoolConstant (bool_res);
+
+ case Binary.Operator.GreaterThan:
+ DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+ if (left == null || right == null)
+ return null;
+
+ bool_res = false;
+ if (left is DoubleConstant)
+ bool_res = ((DoubleConstant) left).Value >
+ ((DoubleConstant) right).Value;
+ else if (left is FloatConstant)
+ bool_res = ((FloatConstant) left).Value >
+ ((FloatConstant) right).Value;
+ else if (left is ULongConstant)
+ bool_res = ((ULongConstant) left).Value >
+ ((ULongConstant) right).Value;
+ else if (left is LongConstant)
+ bool_res = ((LongConstant) left).Value >
+ ((LongConstant) right).Value;
+ else if (left is UIntConstant)
+ bool_res = ((UIntConstant) left).Value >
+ ((UIntConstant) right).Value;
+ else if (left is IntConstant)
+ bool_res = ((IntConstant) left).Value >
+ ((IntConstant) right).Value;
+ else
+ return null;
+
+ return new BoolConstant (bool_res);
+
+ case Binary.Operator.GreaterThanOrEqual:
+ DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+ if (left == null || right == null)
+ return null;
+
+ bool_res = false;
+ if (left is DoubleConstant)
+ bool_res = ((DoubleConstant) left).Value >=
+ ((DoubleConstant) right).Value;
+ else if (left is FloatConstant)
+ bool_res = ((FloatConstant) left).Value >=
+ ((FloatConstant) right).Value;
+ else if (left is ULongConstant)
+ bool_res = ((ULongConstant) left).Value >=
+ ((ULongConstant) right).Value;
+ else if (left is LongConstant)
+ bool_res = ((LongConstant) left).Value >=
+ ((LongConstant) right).Value;
+ else if (left is UIntConstant)
+ bool_res = ((UIntConstant) left).Value >=
+ ((UIntConstant) right).Value;
+ else if (left is IntConstant)
+ bool_res = ((IntConstant) left).Value >=
+ ((IntConstant) right).Value;
+ else
+ return null;
+
+ return new BoolConstant (bool_res);
+
+ case Binary.Operator.LessThanOrEqual:
+ DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+ if (left == null || right == null)
+ return null;
+
+ bool_res = false;
+ if (left is DoubleConstant)
+ bool_res = ((DoubleConstant) left).Value <=
+ ((DoubleConstant) right).Value;
+ else if (left is FloatConstant)
+ bool_res = ((FloatConstant) left).Value <=
+ ((FloatConstant) right).Value;
+ else if (left is ULongConstant)
+ bool_res = ((ULongConstant) left).Value <=
+ ((ULongConstant) right).Value;
+ else if (left is LongConstant)
+ bool_res = ((LongConstant) left).Value <=
+ ((LongConstant) right).Value;
+ else if (left is UIntConstant)
+ bool_res = ((UIntConstant) left).Value <=
+ ((UIntConstant) right).Value;
+ else if (left is IntConstant)
+ bool_res = ((IntConstant) left).Value <=
+ ((IntConstant) right).Value;
+ else
+ return null;
+
+ return new BoolConstant (bool_res);
+ }
+
+ return null;
+ }
+ }
+}