right = right.ToDecimal (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 ||
- (other.IsZeroInteger && other is IntConstant));
-
- if (need_check &&
- !Convert.ImplicitConversionExists (ec, match, other.Type)) {
- match.Error_ValueCannotBeConverted (loc, other.Type, false);
- left = null;
- right = null;
- return;
- }
-
if (left is EnumConstant)
left = ((EnumConstant) left).Child;
if (right is EnumConstant)
static public Expression BinaryFold (EmitContext ec, Binary.Operator oper,
Constant left, Constant right, Location loc)
{
+ if (left is NullCast)
+ return BinaryFold (ec, oper, ((NullCast)left).child, right, loc);
+
+ if (right is NullCast)
+ return BinaryFold (ec, oper, left, ((NullCast)right).child, loc);
+
Type lt = left.Type;
Type rt = right.Type;
Type result_type = null;
right = ((EnumConstant) right).Child;
}
+ if (left is BoolConstant && right is BoolConstant) {
+ bool lv = ((BoolConstant) left ).Value;
+ bool rv = ((BoolConstant) right).Value;
+ 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);
+ default:
+ throw new InternalErrorException ("Invalid operator on booleans: " + oper);
+ }
+ }
+
Type wrap_as;
Constant result = null;
switch (oper){
Error_CompileTimeOverflow (loc);
}
- if (wrap_as != null)
- return new EnumConstant (result, wrap_as);
+ if (wrap_as != null) {
+ try {
+ return result.TryReduce (ec, wrap_as, loc);
+ }
+ catch (OverflowException) {
+ return null;
+ }
+ }
else
return result;
} catch (OverflowException){
Error_CompileTimeOverflow (loc);
}
- if (wrap_as != null)
- return new EnumConstant (result, wrap_as);
- else
- return result;
+
+ if (wrap_as != null) {
+ try {
+ return result.TryReduce (ec, wrap_as, loc);
+ }
+ catch (OverflowException) {
+ return null;
+ }
+ }
+
+ return result;
case Binary.Operator.Multiply:
DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
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, left.Location);
- }
- break;
-
- case Binary.Operator.LogicalOr:
- if (left is BoolConstant && right is BoolConstant){
- return new BoolConstant (
- ((BoolConstant) left).Value ||
- ((BoolConstant) right).Value, left.Location);
- }
- break;
-
case Binary.Operator.Equality:
if (left is BoolConstant && right is BoolConstant){
return new BoolConstant (