//
// Author:
// Miguel de Icaza (miguel@ximian.com)
+// Marek Safar (marek.safar@seznam.cz)
//
-// (C) 2002, 2003 Ximian, Inc.
-//
-
+// Copyright 2002, 2003 Ximian, Inc.
+// Copyright 2003-2008, Novell, Inc.
+//
using System;
namespace Mono.CSharp {
public class ConstantFold {
+ public static readonly Type[] binary_promotions = new Type[] {
+ TypeManager.decimal_type, TypeManager.double_type, TypeManager.float_type,
+ TypeManager.uint64_type, TypeManager.int64_type, TypeManager.uint32_type };
+
//
// 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)
+ static bool DoBinaryNumericPromotions (ref Constant left, ref Constant right)
{
- 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);
+ Type ltype = left.Type;
+ Type rtype = right.Type;
- 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);
+ foreach (Type t in binary_promotions) {
+ if (t == ltype)
+ return t == rtype || ConvertPromotion (ref right, ref left, t);
- 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 (t == rtype)
+ return t == ltype || ConvertPromotion (ref left, ref right, t);
+ }
- if (need_check &&
- !Convert.ImplicitConversionExists (ec, match, other.Type)) {
- Convert.Error_CannotImplicitConversion (loc, match.Type, other.Type);
- left = null;
- right = null;
- return;
- }
+ left = left.ConvertImplicitly (TypeManager.int32_type);
+ right = right.ConvertImplicitly (TypeManager.int32_type);
+ return left != null && right != null;
+ }
- if (left is EnumConstant)
- left = ((EnumConstant) left).Child;
- if (right is EnumConstant)
- right = ((EnumConstant) right).Child;
- return;
+ static bool ConvertPromotion (ref Constant prim, ref Constant second, Type type)
+ {
+ Constant c = prim.ConvertImplicitly (type);
+ if (c != null) {
+ prim = c;
+ return true;
+ }
- } else {
- //
- // Force conversions to int32
- //
- if (!(left is IntConstant))
- left = left.ToInt (loc);
- if (!(right is IntConstant))
- right = right.ToInt (loc);
+ if (type == TypeManager.uint32_type) {
+ type = TypeManager.int64_type;
+ prim = prim.ConvertImplicitly (type);
+ second = second.ConvertImplicitly (type);
+ return prim != null && second != null;
}
- return;
+
+ return false;
}
- static void Error_CompileTimeOverflow (Location loc)
+ internal static void Error_CompileTimeOverflow (Location loc)
{
Report.Error (220, loc, "The operation overflows at compile time in checked mode");
}
///
/// Returns null if the expression can not be folded.
/// </summary>
- static public Expression BinaryFold (EmitContext ec, Binary.Operator oper,
+ static public Constant BinaryFold (EmitContext ec, Binary.Operator oper,
Constant left, Constant right, Location loc)
{
+ Constant result = null;
+
+ if (left is EmptyConstantCast)
+ return BinaryFold (ec, oper, ((EmptyConstantCast)left).child, right, loc);
+
+ if (left is SideEffectConstant) {
+ result = BinaryFold (ec, oper, ((SideEffectConstant) left).value, right, loc);
+ if (result == null)
+ return null;
+ return new SideEffectConstant (result, left, loc);
+ }
+
+ if (right is EmptyConstantCast)
+ return BinaryFold (ec, oper, left, ((EmptyConstantCast)right).child, loc);
+
+ if (right is SideEffectConstant) {
+ result = BinaryFold (ec, oper, left, ((SideEffectConstant) right).value, loc);
+ if (result == null)
+ return null;
+ return new SideEffectConstant (result, right, 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;
+
+ if (lt == TypeManager.bool_type && lt == rt) {
+ bool lv = (bool) left.GetValue ();
+ bool rv = (bool) right.GetValue ();
+ switch (oper) {
+ case Binary.Operator.BitwiseAnd:
+ case Binary.Operator.LogicalAnd:
+ return new BoolConstant (lv && rv, left.Location);
+ case Binary.Operator.BitwiseOr:
+ case Binary.Operator.LogicalOr:
+ return new BoolConstant (lv || rv, left.Location);
+ case Binary.Operator.ExclusiveOr:
+ return new BoolConstant (lv ^ rv, left.Location);
+ case Binary.Operator.Equality:
+ return new BoolConstant (lv == rv, left.Location);
+ case Binary.Operator.Inequality:
+ return new BoolConstant (lv != rv, left.Location);
+ }
+ return null;
+ }
//
- // During an enum evaluation, we need to unwrap enumerations
+ // During an enum evaluation, none of the rules are valid
+ // Not sure whether it is bug in csc or in documentation
//
if (ec.InEnumContext){
if (left is EnumConstant)
if (right is EnumConstant)
right = ((EnumConstant) right).Child;
+ } else if (left is EnumConstant && rt == lt) {
+ switch (oper){
+ ///
+ /// E operator |(E x, E y);
+ /// E operator &(E x, E y);
+ /// E operator ^(E x, E y);
+ ///
+ case Binary.Operator.BitwiseOr:
+ case Binary.Operator.BitwiseAnd:
+ case Binary.Operator.ExclusiveOr:
+ return BinaryFold (ec, oper, ((EnumConstant)left).Child,
+ ((EnumConstant)right).Child, loc).TryReduce (ec, lt, loc);
+
+ ///
+ /// U operator -(E x, E y);
+ ///
+ case Binary.Operator.Subtraction:
+ result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
+ return result.TryReduce (ec, ((EnumConstant)left).Child.Type, loc);
+
+ ///
+ /// bool operator ==(E x, E y);
+ /// bool operator !=(E x, E y);
+ /// bool operator <(E x, E y);
+ /// bool operator >(E x, E y);
+ /// bool operator <=(E x, E y);
+ /// bool operator >=(E x, E y);
+ ///
+ case Binary.Operator.Equality:
+ case Binary.Operator.Inequality:
+ case Binary.Operator.LessThan:
+ case Binary.Operator.GreaterThan:
+ case Binary.Operator.LessThanOrEqual:
+ case Binary.Operator.GreaterThanOrEqual:
+ return BinaryFold(ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
+ }
+ return null;
}
- 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)
+ if (!DoBinaryNumericPromotions (ref left, ref right))
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;
+ return new IntConstant (res, left.Location);
+ }
+ if (left is UIntConstant){
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;
+ return new UIntConstant (res, left.Location);
+ }
+ if (left is LongConstant){
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;
+ return new LongConstant (res, left.Location);
+ }
+ if (left is ULongConstant){
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);
+ return new ULongConstant (res, left.Location);
}
break;
case Binary.Operator.BitwiseAnd:
- DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
- if (left == null || right == null)
+ if (!DoBinaryNumericPromotions (ref left, ref right))
return null;
+ ///
+ /// int operator &(int x, int y);
+ /// uint operator &(uint x, uint y);
+ /// long operator &(long x, long y);
+ /// ulong operator &(ulong x, ulong y);
+ ///
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;
+ return new IntConstant (res, left.Location);
+ }
+ if (left is UIntConstant){
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;
+ return new UIntConstant (res, left.Location);
+ }
+ if (left is LongConstant){
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;
+ return new LongConstant (res, left.Location);
+ }
+ if (left is ULongConstant){
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);
+ return new ULongConstant (res, left.Location);
}
break;
case Binary.Operator.ExclusiveOr:
- DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
- if (left == null || right == null)
+ if (!DoBinaryNumericPromotions (ref left, ref right))
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;
+ return new IntConstant (res, left.Location);
+ }
+ if (left is UIntConstant){
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;
+ return new UIntConstant (res, left.Location);
+ }
+ if (left is LongConstant){
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;
+ return new LongConstant (res, left.Location);
+ }
+ if (left is ULongConstant){
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);
+ return new ULongConstant (res, left.Location);
}
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)
+ if (lt == TypeManager.string_type || rt == TypeManager.string_type){
+ if (lt == TypeManager.string_type && rt == TypeManager.string_type)
return new StringConstant (
((StringConstant) left).Value +
- ((StringConstant) right).Value);
+ ((StringConstant) right).Value, left.Location);
return null;
}
+ if (lt == TypeManager.null_type && lt == rt)
+ return left;
+
//
// 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;
+ EnumConstant lc = left as EnumConstant;
+ EnumConstant rc = right as EnumConstant;
+ if (lc != null || rc != null){
+ if (lc == null) {
+ lc = rc;
+ lt = lc.Type;
+ right = left;
}
- if (((EnumConstant) left).Child.Type != right.Type)
+
+ // U has to be implicitly convetible to E.base
+ right = right.ConvertImplicitly (lc.Child.Type);
+ if (right == null)
return null;
- wrap_as = left.Type;
- } else if (right is EnumConstant){
- if (((EnumConstant) right).Child.Type != left.Type)
+ result = BinaryFold (ec, oper, lc.Child, right, loc);
+ if (result == null)
return null;
- wrap_as = right.Type;
+
+ result = result.TryReduce (ec, lt, loc);
+ if (result == null)
+ return null;
+
+ return new EnumConstant (result, lt);
}
- result = null;
- DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
- if (left == null || right == null)
+ if (!DoBinaryNumericPromotions (ref left, ref right))
return null;
try {
res = unchecked (((DoubleConstant) left).Value +
((DoubleConstant) right).Value);
- result = new DoubleConstant (res);
- } else if (left is FloatConstant){
+ return new DoubleConstant (res, left.Location);
+ }
+ if (left is FloatConstant){
float res;
if (ec.ConstantCheckState)
res = unchecked (((FloatConstant) left).Value +
((FloatConstant) right).Value);
- result = new FloatConstant (res);
+ result = new FloatConstant (res, left.Location);
} else if (left is ULongConstant){
ulong res;
res = unchecked (((ULongConstant) left).Value +
((ULongConstant) right).Value);
- result = new ULongConstant (res);
+ result = new ULongConstant (res, left.Location);
} else if (left is LongConstant){
long res;
res = unchecked (((LongConstant) left).Value +
((LongConstant) right).Value);
- result = new LongConstant (res);
+ result = new LongConstant (res, left.Location);
} else if (left is UIntConstant){
uint res;
res = unchecked (((UIntConstant) left).Value +
((UIntConstant) right).Value);
- result = new UIntConstant (res);
+ result = new UIntConstant (res, left.Location);
} else if (left is IntConstant){
int res;
res = unchecked (((IntConstant) left).Value +
((IntConstant) right).Value);
- result = new IntConstant (res);
+ result = new IntConstant (res, left.Location);
+ } else if (left is DecimalConstant) {
+ decimal res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((DecimalConstant) left).Value +
+ ((DecimalConstant) right).Value);
+ else
+ res = unchecked (((DecimalConstant) left).Value +
+ ((DecimalConstant) right).Value);
+
+ result = new DecimalConstant (res, left.Location);
} else {
- throw new Exception ( "Unexepected input: " + left);
+ throw new Exception ( "Unexepected addition input: " + left);
}
} catch (OverflowException){
Error_CompileTimeOverflow (loc);
}
- if (wrap_as != null)
- return new EnumConstant (result, wrap_as);
- else
- return result;
+ 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;
+ lc = left as EnumConstant;
+ rc = right as EnumConstant;
+ if (lc != null || rc != null){
+ if (lc == null) {
+ lc = rc;
+ lt = lc.Type;
+ right = left;
}
- if (((EnumConstant) left).Child.Type != right.Type)
+
+ // U has to be implicitly convetible to E.base
+ right = right.ConvertImplicitly (lc.Child.Type);
+ if (right == null)
+ return null;
+
+ result = BinaryFold (ec, oper, lc.Child, right, loc);
+ if (result == null)
return null;
- wrap_as = left.Type;
- } else if (right is EnumConstant){
- if (((EnumConstant) right).Child.Type != left.Type)
+ result = result.TryReduce (ec, lt, loc);
+ if (result == null)
return null;
- wrap_as = right.Type;
+
+ return new EnumConstant (result, lt);
}
- DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
- if (left == null || right == null)
+ if (!DoBinaryNumericPromotions (ref left, ref right))
return null;
try {
res = unchecked (((DoubleConstant) left).Value -
((DoubleConstant) right).Value);
- result = new DoubleConstant (res);
+ result = new DoubleConstant (res, left.Location);
} else if (left is FloatConstant){
float res;
res = unchecked (((FloatConstant) left).Value -
((FloatConstant) right).Value);
- result = new FloatConstant (res);
+ result = new FloatConstant (res, left.Location);
} else if (left is ULongConstant){
ulong res;
res = unchecked (((ULongConstant) left).Value -
((ULongConstant) right).Value);
- result = new ULongConstant (res);
+ result = new ULongConstant (res, left.Location);
} else if (left is LongConstant){
long res;
res = unchecked (((LongConstant) left).Value -
((LongConstant) right).Value);
- result = new LongConstant (res);
+ result = new LongConstant (res, left.Location);
} else if (left is UIntConstant){
uint res;
res = unchecked (((UIntConstant) left).Value -
((UIntConstant) right).Value);
- result = new UIntConstant (res);
+ result = new UIntConstant (res, left.Location);
} else if (left is IntConstant){
int res;
res = unchecked (((IntConstant) left).Value -
((IntConstant) right).Value);
- result = new IntConstant (res);
+ result = new IntConstant (res, left.Location);
+ } else if (left is DecimalConstant) {
+ decimal res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((DecimalConstant) left).Value -
+ ((DecimalConstant) right).Value);
+ else
+ res = unchecked (((DecimalConstant) left).Value -
+ ((DecimalConstant) right).Value);
+
+ return new DecimalConstant (res, left.Location);
} else {
- throw new Exception ( "Unexepected input: " + left);
+ throw new Exception ( "Unexepected subtraction input: " + left);
}
} catch (OverflowException){
Error_CompileTimeOverflow (loc);
}
- if (wrap_as != null)
- return new EnumConstant (result, wrap_as);
- else
- return result;
+
+ return result;
case Binary.Operator.Multiply:
- DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
- if (left == null || right == null)
+ if (!DoBinaryNumericPromotions (ref left, ref right))
return null;
try {
if (ec.ConstantCheckState)
res = checked (((DoubleConstant) left).Value *
- ((DoubleConstant) right).Value);
+ ((DoubleConstant) right).Value);
else
res = unchecked (((DoubleConstant) left).Value *
- ((DoubleConstant) right).Value);
+ ((DoubleConstant) right).Value);
- return new DoubleConstant (res);
+ return new DoubleConstant (res, left.Location);
} else if (left is FloatConstant){
float res;
if (ec.ConstantCheckState)
res = checked (((FloatConstant) left).Value *
- ((FloatConstant) right).Value);
+ ((FloatConstant) right).Value);
else
res = unchecked (((FloatConstant) left).Value *
- ((FloatConstant) right).Value);
+ ((FloatConstant) right).Value);
- return new FloatConstant (res);
+ return new FloatConstant (res, left.Location);
} else if (left is ULongConstant){
ulong res;
if (ec.ConstantCheckState)
res = checked (((ULongConstant) left).Value *
- ((ULongConstant) right).Value);
+ ((ULongConstant) right).Value);
else
res = unchecked (((ULongConstant) left).Value *
- ((ULongConstant) right).Value);
+ ((ULongConstant) right).Value);
- return new ULongConstant (res);
+ return new ULongConstant (res, left.Location);
} else if (left is LongConstant){
long res;
if (ec.ConstantCheckState)
res = checked (((LongConstant) left).Value *
- ((LongConstant) right).Value);
+ ((LongConstant) right).Value);
else
res = unchecked (((LongConstant) left).Value *
- ((LongConstant) right).Value);
+ ((LongConstant) right).Value);
- return new LongConstant (res);
+ return new LongConstant (res, left.Location);
} else if (left is UIntConstant){
uint res;
if (ec.ConstantCheckState)
res = checked (((UIntConstant) left).Value *
- ((UIntConstant) right).Value);
+ ((UIntConstant) right).Value);
else
res = unchecked (((UIntConstant) left).Value *
- ((UIntConstant) right).Value);
+ ((UIntConstant) right).Value);
- return new UIntConstant (res);
+ return new UIntConstant (res, left.Location);
} else if (left is IntConstant){
int res;
if (ec.ConstantCheckState)
res = checked (((IntConstant) left).Value *
- ((IntConstant) right).Value);
+ ((IntConstant) right).Value);
else
res = unchecked (((IntConstant) left).Value *
- ((IntConstant) right).Value);
+ ((IntConstant) right).Value);
- return new IntConstant (res);
+ return new IntConstant (res, left.Location);
+ } else if (left is DecimalConstant) {
+ decimal res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((DecimalConstant) left).Value *
+ ((DecimalConstant) right).Value);
+ else
+ res = unchecked (((DecimalConstant) left).Value *
+ ((DecimalConstant) right).Value);
+
+ return new DecimalConstant (res, left.Location);
} else {
- throw new Exception ( "Unexepected input: " + left);
+ throw new Exception ( "Unexepected multiply 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)
+ if (!DoBinaryNumericPromotions (ref left, ref right))
return null;
try {
if (ec.ConstantCheckState)
res = checked (((DoubleConstant) left).Value /
- ((DoubleConstant) right).Value);
+ ((DoubleConstant) right).Value);
else
res = unchecked (((DoubleConstant) left).Value /
- ((DoubleConstant) right).Value);
+ ((DoubleConstant) right).Value);
- return new DoubleConstant (res);
+ return new DoubleConstant (res, left.Location);
} else if (left is FloatConstant){
float res;
if (ec.ConstantCheckState)
res = checked (((FloatConstant) left).Value /
- ((FloatConstant) right).Value);
+ ((FloatConstant) right).Value);
else
res = unchecked (((FloatConstant) left).Value /
- ((FloatConstant) right).Value);
+ ((FloatConstant) right).Value);
- return new FloatConstant (res);
+ return new FloatConstant (res, left.Location);
} else if (left is ULongConstant){
ulong res;
if (ec.ConstantCheckState)
res = checked (((ULongConstant) left).Value /
- ((ULongConstant) right).Value);
+ ((ULongConstant) right).Value);
else
res = unchecked (((ULongConstant) left).Value /
- ((ULongConstant) right).Value);
+ ((ULongConstant) right).Value);
- return new ULongConstant (res);
+ return new ULongConstant (res, left.Location);
} else if (left is LongConstant){
long res;
if (ec.ConstantCheckState)
res = checked (((LongConstant) left).Value /
- ((LongConstant) right).Value);
+ ((LongConstant) right).Value);
else
res = unchecked (((LongConstant) left).Value /
- ((LongConstant) right).Value);
+ ((LongConstant) right).Value);
- return new LongConstant (res);
+ return new LongConstant (res, left.Location);
} else if (left is UIntConstant){
uint res;
if (ec.ConstantCheckState)
res = checked (((UIntConstant) left).Value /
- ((UIntConstant) right).Value);
+ ((UIntConstant) right).Value);
else
res = unchecked (((UIntConstant) left).Value /
- ((UIntConstant) right).Value);
+ ((UIntConstant) right).Value);
- return new UIntConstant (res);
+ return new UIntConstant (res, left.Location);
} else if (left is IntConstant){
int res;
if (ec.ConstantCheckState)
res = checked (((IntConstant) left).Value /
- ((IntConstant) right).Value);
+ ((IntConstant) right).Value);
else
res = unchecked (((IntConstant) left).Value /
- ((IntConstant) right).Value);
+ ((IntConstant) right).Value);
+
+ return new IntConstant (res, left.Location);
+ } else if (left is DecimalConstant) {
+ decimal res;
+
+ if (ec.ConstantCheckState)
+ res = checked (((DecimalConstant) left).Value /
+ ((DecimalConstant) right).Value);
+ else
+ res = unchecked (((DecimalConstant) left).Value /
+ ((DecimalConstant) right).Value);
- return new IntConstant (res);
+ return new DecimalConstant (res, left.Location);
} else {
- throw new Exception ( "Unexepected input: " + left);
+ throw new Exception ( "Unexepected division input: " + left);
}
} catch (OverflowException){
Error_CompileTimeOverflow (loc);
break;
case Binary.Operator.Modulus:
- DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
- if (left == null || right == null)
+ if (!DoBinaryNumericPromotions (ref left, ref right))
return null;
try {
res = unchecked (((DoubleConstant) left).Value %
((DoubleConstant) right).Value);
- return new DoubleConstant (res);
+ return new DoubleConstant (res, left.Location);
} else if (left is FloatConstant){
float res;
res = unchecked (((FloatConstant) left).Value %
((FloatConstant) right).Value);
- return new FloatConstant (res);
+ return new FloatConstant (res, left.Location);
} else if (left is ULongConstant){
ulong res;
res = unchecked (((ULongConstant) left).Value %
((ULongConstant) right).Value);
- return new ULongConstant (res);
+ return new ULongConstant (res, left.Location);
} else if (left is LongConstant){
long res;
res = unchecked (((LongConstant) left).Value %
((LongConstant) right).Value);
- return new LongConstant (res);
+ return new LongConstant (res, left.Location);
} else if (left is UIntConstant){
uint res;
res = unchecked (((UIntConstant) left).Value %
((UIntConstant) right).Value);
- return new UIntConstant (res);
+ return new UIntConstant (res, left.Location);
} else if (left is IntConstant){
int res;
res = unchecked (((IntConstant) left).Value %
((IntConstant) right).Value);
- return new IntConstant (res);
+ return new IntConstant (res, left.Location);
} else {
- throw new Exception ( "Unexepected input: " + left);
+ throw new Exception ( "Unexepected modulus input: " + left);
}
} catch (DivideByZeroException){
Report.Error (020, loc, "Division by constant zero");
// There is no overflow checking on left shift
//
case Binary.Operator.LeftShift:
- IntConstant ic = right.ToInt (loc);
+ IntConstant ic = right.ConvertImplicitly (TypeManager.int32_type) as IntConstant;
if (ic == null){
- Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
+ Binary.Error_OperatorCannotBeApplied (left, right, oper, loc);
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);
+ int lshift_val = ic.Value;
+ if (left.Type == TypeManager.uint64_type)
+ return new ULongConstant (((ULongConstant)left).Value << lshift_val, left.Location);
+ if (left.Type == TypeManager.int64_type)
+ return new LongConstant (((LongConstant)left).Value << lshift_val, left.Location);
+ if (left.Type == TypeManager.uint32_type)
+ return new UIntConstant (((UIntConstant)left).Value << lshift_val, left.Location);
+
+ left = left.ConvertImplicitly (TypeManager.int32_type);
+ if (left.Type == TypeManager.int32_type)
+ return new IntConstant (((IntConstant)left).Value << lshift_val, left.Location);
+
+ Binary.Error_OperatorCannotBeApplied (left, right, oper, loc);
break;
//
// There is no overflow checking on right shift
//
case Binary.Operator.RightShift:
- IntConstant sic = right.ToInt (loc);
+ IntConstant sic = right.ConvertImplicitly (TypeManager.int32_type) as IntConstant;
if (sic == null){
- Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
+ Binary.Error_OperatorCannotBeApplied (left, right, oper, loc); ;
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);
- }
+ if (left.Type == TypeManager.uint64_type)
+ return new ULongConstant (((ULongConstant)left).Value >> rshift_val, left.Location);
+ if (left.Type == TypeManager.int64_type)
+ return new LongConstant (((LongConstant)left).Value >> rshift_val, left.Location);
+ if (left.Type == TypeManager.uint32_type)
+ return new UIntConstant (((UIntConstant)left).Value >> rshift_val, left.Location);
+
+ left = left.ConvertImplicitly (TypeManager.int32_type);
+ if (left.Type == TypeManager.int32_type)
+ return new IntConstant (((IntConstant)left).Value >> rshift_val, left.Location);
+
+ Binary.Error_OperatorCannotBeApplied (left, right, oper, loc);
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 NullLiteral){
+ if (right is NullLiteral)
+ return new BoolConstant (true, left.Location);
+ else if (right is StringConstant)
+ return new BoolConstant (
+ ((StringConstant) right).Value == null, left.Location);
+ } else if (right is NullLiteral) {
+ if (left is NullLiteral)
+ return new BoolConstant (true, left.Location);
+ else if (left is StringConstant)
+ return new BoolConstant (
+ ((StringConstant) left).Value == null, left.Location);
}
if (left is StringConstant && right is StringConstant){
return new BoolConstant (
((StringConstant) left).Value ==
- ((StringConstant) right).Value);
+ ((StringConstant) right).Value, left.Location);
}
-
- DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
- if (left == null || right == null)
+
+ if (!DoBinaryNumericPromotions (ref left, ref right))
return null;
bool_res = false;
else
return null;
- return new BoolConstant (bool_res);
+ return new BoolConstant (bool_res, left.Location);
case Binary.Operator.Inequality:
- if (left is BoolConstant && right is BoolConstant){
- return new BoolConstant (
- ((BoolConstant) left).Value !=
- ((BoolConstant) right).Value);
+ if (left is NullLiteral) {
+ if (right is NullLiteral)
+ return new BoolConstant (false, left.Location);
+ else if (right is StringConstant)
+ return new BoolConstant (
+ ((StringConstant) right).Value != null, left.Location);
+ } else if (right is NullLiteral) {
+ if (left is NullLiteral)
+ return new BoolConstant (false, left.Location);
+ else if (left is StringConstant)
+ return new BoolConstant (
+ ((StringConstant) left).Value != null, left.Location);
}
if (left is StringConstant && right is StringConstant){
return new BoolConstant (
((StringConstant) left).Value !=
- ((StringConstant) right).Value);
+ ((StringConstant) right).Value, left.Location);
}
- DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
- if (left == null || right == null)
+
+ if (!DoBinaryNumericPromotions (ref left, ref right))
return null;
bool_res = false;
else
return null;
- return new BoolConstant (bool_res);
+ return new BoolConstant (bool_res, left.Location);
case Binary.Operator.LessThan:
- DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
- if (left == null || right == null)
+ if (!DoBinaryNumericPromotions (ref left, ref right))
return null;
bool_res = false;
else
return null;
- return new BoolConstant (bool_res);
+ return new BoolConstant (bool_res, left.Location);
case Binary.Operator.GreaterThan:
- DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
- if (left == null || right == null)
+ if (!DoBinaryNumericPromotions (ref left, ref right))
return null;
bool_res = false;
else
return null;
- return new BoolConstant (bool_res);
+ return new BoolConstant (bool_res, left.Location);
case Binary.Operator.GreaterThanOrEqual:
- DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
- if (left == null || right == null)
+ if (!DoBinaryNumericPromotions (ref left, ref right))
return null;
bool_res = false;
else
return null;
- return new BoolConstant (bool_res);
+ return new BoolConstant (bool_res, left.Location);
case Binary.Operator.LessThanOrEqual:
- DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
- if (left == null || right == null)
+ if (!DoBinaryNumericPromotions (ref left, ref right))
return null;
bool_res = false;
else
return null;
- return new BoolConstant (bool_res);
+ return new BoolConstant (bool_res, left.Location);
}
return null;