X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fcfold.cs;h=f19c1a400e33d6e0f676f93f4cdf15f3af415129;hb=65b5d9b115844180bf16108876d7704b877a7281;hp=8724e48b52d7196baf82672bb14f3f673a22a225;hpb=f4774442eaf92333012ae8b0a431739b4efe22bf;p=mono.git diff --git a/mcs/mcs/cfold.cs b/mcs/mcs/cfold.cs index 8724e48b52d..f19c1a400e3 100644 --- a/mcs/mcs/cfold.cs +++ b/mcs/mcs/cfold.cs @@ -149,7 +149,7 @@ namespace Mono.CSharp { case Binary.Operator.ExclusiveOr: result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc); if (result != null) - result = result.TryReduce (ec, lt); + result = result.Reduce (ec, lt); return result; /// @@ -158,7 +158,7 @@ namespace Mono.CSharp { case Binary.Operator.Subtraction: result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc); if (result != null) - result = result.TryReduce (ec, EnumSpec.GetUnderlyingType (lt)); + result = result.Reduce (ec, EnumSpec.GetUnderlyingType (lt)); return result; /// @@ -183,11 +183,11 @@ namespace Mono.CSharp { switch (oper){ case Binary.Operator.BitwiseOr: // - // bool? operator &(bool? x, bool? y); + // bool? operator |(bool? x, bool? y); // if ((lt.BuiltinType == BuiltinTypeSpec.Type.Bool && right is NullLiteral) || (rt.BuiltinType == BuiltinTypeSpec.Type.Bool && left is NullLiteral)) { - var b = new Nullable.LiftedBinaryOperator (oper, left, right).Resolve (ec); + var b = new Binary (oper, left, right).ResolveOperator (ec); // false | null => null // null | false => null @@ -231,7 +231,7 @@ namespace Mono.CSharp { // if ((lt.BuiltinType == BuiltinTypeSpec.Type.Bool && right is NullLiteral) || (rt.BuiltinType == BuiltinTypeSpec.Type.Bool && left is NullLiteral)) { - var b = new Nullable.LiftedBinaryOperator (oper, left, right).Resolve (ec); + var b = new Binary (oper, left, right).ResolveOperator (ec); // false & null => false // null & false => false @@ -299,25 +299,51 @@ namespace Mono.CSharp { break; case Binary.Operator.Addition: - if (lt == InternalType.NullLiteral) - return right; - - if (rt == InternalType.NullLiteral) - return left; - // - // If both sides are strings, then concatenate, if - // one is a string, and the other is not, then defer - // to runtime concatenation + // If both sides are strings, then concatenate + // + // string operator + (string x, string y) // if (lt.BuiltinType == BuiltinTypeSpec.Type.String || rt.BuiltinType == BuiltinTypeSpec.Type.String){ if (lt == rt) return new StringConstant (ec.BuiltinTypes, (string)left.GetValue () + (string)right.GetValue (), left.Location); - + + if (lt == InternalType.NullLiteral || left.IsNull) + return new StringConstant (ec.BuiltinTypes, "" + right.GetValue (), left.Location); + + if (rt == InternalType.NullLiteral || right.IsNull) + return new StringConstant (ec.BuiltinTypes, left.GetValue () + "", left.Location); + return null; } + // + // string operator + (string x, object y) + // + if (lt == InternalType.NullLiteral) { + if (rt.BuiltinType == BuiltinTypeSpec.Type.Object) + return new StringConstant (ec.BuiltinTypes, "" + right.GetValue (), left.Location); + + if (lt == rt) { + ec.Report.Error (34, loc, "Operator `{0}' is ambiguous on operands of type `{1}' and `{2}'", + "+", lt.GetSignatureForError (), rt.GetSignatureForError ()); + return null; + } + + return right; + } + + // + // string operator + (object x, string y) + // + if (rt == InternalType.NullLiteral) { + if (lt.BuiltinType == BuiltinTypeSpec.Type.Object) + return new StringConstant (ec.BuiltinTypes, right.GetValue () + "", left.Location); + + return left; + } + // // handle "E operator + (E x, U y)" // handle "E operator + (Y y, E x)" @@ -340,9 +366,9 @@ namespace Mono.CSharp { if (result == null) return null; - result = result.TryReduce (ec, lt); - if (result == null) - return null; + result = result.Reduce (ec, lt); + if (result == null || lt.IsEnum) + return result; return new EnumConstant (result, lt); } @@ -364,14 +390,14 @@ namespace Mono.CSharp { return new DoubleConstant (ec.BuiltinTypes, res, left.Location); } if (left is FloatConstant){ - float res; - + double a, b, res; + a = ((FloatConstant) left).DoubleValue; + b = ((FloatConstant) right).DoubleValue; + if (ec.ConstantCheckState) - res = checked (((FloatConstant) left).Value + - ((FloatConstant) right).Value); + res = checked (a + b); else - res = unchecked (((FloatConstant) left).Value + - ((FloatConstant) right).Value); + res = unchecked (a + b); result = new FloatConstant (ec.BuiltinTypes, res, left.Location); } else if (left is ULongConstant){ @@ -443,33 +469,43 @@ namespace Mono.CSharp { // lc = left as EnumConstant; rc = right as EnumConstant; - if (lc != null || rc != null){ + if (lc != null || rc != null) { + TypeSpec res_type; if (lc == null) { - lc = rc; - lt = lc.Type; - right = left; - } + res_type = right.Type; - // U has to be implicitly convetible to E.base - right = right.ConvertImplicitly (lc.Child.Type); - if (right == null) - return null; + // Y has to be implicitly convertible to E.base + left = left.ConvertImplicitly (rc.Child.Type); + if (left == null) + return null; - result = BinaryFold (ec, oper, lc.Child, right, loc); + right = rc.Child; + } else { + res_type = left.Type; + + // U has to be implicitly convertible to E.base + right = right.ConvertImplicitly (lc.Child.Type); + if (right == null) + return null; + + left = lc.Child; + } + + result = BinaryFold (ec, oper, left, right, loc); if (result == null) return null; - result = result.TryReduce (ec, lt); + result = result.Reduce (ec, res_type); if (result == null) return null; - return new EnumConstant (result, lt); + return new EnumConstant (result, res_type); } if (left is NullLiteral && right is NullLiteral) { var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); lifted_int.ResolveAsType (ec); - return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec); + return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec); } if (!DoBinaryNumericPromotions (ec, ref left, ref right)) @@ -488,14 +524,14 @@ namespace Mono.CSharp { result = new DoubleConstant (ec.BuiltinTypes, res, left.Location); } else if (left is FloatConstant){ - float res; - + double a, b, res; + a = ((FloatConstant) left).DoubleValue; + b = ((FloatConstant) right).DoubleValue; + if (ec.ConstantCheckState) - res = checked (((FloatConstant) left).Value - - ((FloatConstant) right).Value); + res = checked (a - b); else - res = unchecked (((FloatConstant) left).Value - - ((FloatConstant) right).Value); + res = unchecked (a - b); result = new FloatConstant (ec.BuiltinTypes, res, left.Location); } else if (left is ULongConstant){ @@ -566,7 +602,7 @@ namespace Mono.CSharp { if (left is NullLiteral && right is NullLiteral) { var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); lifted_int.ResolveAsType (ec); - return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec); + return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec); } if (!DoBinaryNumericPromotions (ec, ref left, ref right)) @@ -585,14 +621,14 @@ namespace Mono.CSharp { return new DoubleConstant (ec.BuiltinTypes, res, left.Location); } else if (left is FloatConstant){ - float res; - + double a, b, res; + a = ((FloatConstant) left).DoubleValue; + b = ((FloatConstant) right).DoubleValue; + if (ec.ConstantCheckState) - res = checked (((FloatConstant) left).Value * - ((FloatConstant) right).Value); + res = checked (a * b); else - res = unchecked (((FloatConstant) left).Value * - ((FloatConstant) right).Value); + res = unchecked (a * b); return new FloatConstant (ec.BuiltinTypes, res, left.Location); } else if (left is ULongConstant){ @@ -662,7 +698,7 @@ namespace Mono.CSharp { if (left is NullLiteral && right is NullLiteral) { var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); lifted_int.ResolveAsType (ec); - return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec); + return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec); } if (!DoBinaryNumericPromotions (ec, ref left, ref right)) @@ -681,14 +717,14 @@ namespace Mono.CSharp { return new DoubleConstant (ec.BuiltinTypes, res, left.Location); } else if (left is FloatConstant){ - float res; - + double a, b, res; + a = ((FloatConstant) left).DoubleValue; + b = ((FloatConstant) right).DoubleValue; + if (ec.ConstantCheckState) - res = checked (((FloatConstant) left).Value / - ((FloatConstant) right).Value); + res = checked (a / b); else - res = unchecked (((FloatConstant) left).Value / - ((FloatConstant) right).Value); + res = unchecked (a / b); return new FloatConstant (ec.BuiltinTypes, res, left.Location); } else if (left is ULongConstant){ @@ -762,7 +798,7 @@ namespace Mono.CSharp { if (left is NullLiteral && right is NullLiteral) { var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); lifted_int.ResolveAsType (ec); - return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec); + return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec); } if (!DoBinaryNumericPromotions (ec, ref left, ref right)) @@ -781,14 +817,14 @@ namespace Mono.CSharp { return new DoubleConstant (ec.BuiltinTypes, res, left.Location); } else if (left is FloatConstant){ - float res; + double a, b, res; + a = ((FloatConstant) left).DoubleValue; + b = ((FloatConstant) right).DoubleValue; if (ec.ConstantCheckState) - res = checked (((FloatConstant) left).Value % - ((FloatConstant) right).Value); + res = checked (a % b); else - res = unchecked (((FloatConstant) left).Value % - ((FloatConstant) right).Value); + res = unchecked (a % b); return new FloatConstant (ec.BuiltinTypes, res, left.Location); } else if (left is ULongConstant){ @@ -835,9 +871,22 @@ namespace Mono.CSharp { ((IntConstant) right).Value); return new IntConstant (ec.BuiltinTypes, res, left.Location); - } else { - throw new Exception ( "Unexepected modulus input: " + left); } + + 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 (ec.BuiltinTypes, res, left.Location); + } + + throw new Exception ( "Unexepected modulus input: " + left); } catch (DivideByZeroException){ ec.Report.Error (20, loc, "Division by constant zero"); } catch (OverflowException){ @@ -852,12 +901,11 @@ namespace Mono.CSharp { if (left is NullLiteral && right is NullLiteral) { var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); lifted_int.ResolveAsType (ec); - return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec); + return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec); } IntConstant ic = right.ConvertImplicitly (ec.BuiltinTypes.Int) as IntConstant; if (ic == null){ - Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); return null; } @@ -873,14 +921,13 @@ namespace Mono.CSharp { // null << value => null if (left is NullLiteral) - return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right).Resolve (ec); + return (Constant) new Binary (oper, left, right).ResolveOperator (ec); left = left.ConvertImplicitly (ec.BuiltinTypes.Int); if (left.Type.BuiltinType == BuiltinTypeSpec.Type.Int) return new IntConstant (ec.BuiltinTypes, ((IntConstant) left).Value << lshift_val, left.Location); - Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); - break; + return null; // // There is no overflow checking on right shift @@ -889,12 +936,11 @@ namespace Mono.CSharp { if (left is NullLiteral && right is NullLiteral) { var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); lifted_int.ResolveAsType (ec); - return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec); + return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec); } IntConstant sic = right.ConvertImplicitly (ec.BuiltinTypes.Int) as IntConstant; if (sic == null){ - Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); ; return null; } int rshift_val = sic.Value; @@ -909,14 +955,13 @@ namespace Mono.CSharp { // null >> value => null if (left is NullLiteral) - return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right).Resolve (ec); + return (Constant) new Binary (oper, left, right).ResolveOperator (ec); left = left.ConvertImplicitly (ec.BuiltinTypes.Int); if (left.Type.BuiltinType == BuiltinTypeSpec.Type.Int) return new IntConstant (ec.BuiltinTypes, ((IntConstant) left).Value >> rshift_val, left.Location); - Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); - break; + return null; case Binary.Operator.Equality: if (TypeSpec.IsReferenceType (lt) && TypeSpec.IsReferenceType (rt) || @@ -943,8 +988,8 @@ namespace Mono.CSharp { bool_res = ((DoubleConstant) left).Value == ((DoubleConstant) right).Value; else if (left is FloatConstant) - bool_res = ((FloatConstant) left).Value == - ((FloatConstant) right).Value; + bool_res = ((FloatConstant) left).DoubleValue == + ((FloatConstant) right).DoubleValue; else if (left is ULongConstant) bool_res = ((ULongConstant) left).Value == ((ULongConstant) right).Value; @@ -987,8 +1032,8 @@ namespace Mono.CSharp { bool_res = ((DoubleConstant) left).Value != ((DoubleConstant) right).Value; else if (left is FloatConstant) - bool_res = ((FloatConstant) left).Value != - ((FloatConstant) right).Value; + bool_res = ((FloatConstant) left).DoubleValue != + ((FloatConstant) right).DoubleValue; else if (left is ULongConstant) bool_res = ((ULongConstant) left).Value != ((ULongConstant) right).Value; @@ -1011,11 +1056,7 @@ namespace Mono.CSharp { if (left is NullLiteral) { var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); lifted_int.ResolveAsType (ec); - return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec); - } - - if (left is Nullable.LiftedNull) { - return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right).Resolve (ec); + return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec); } } @@ -1027,8 +1068,8 @@ namespace Mono.CSharp { bool_res = ((DoubleConstant) left).Value < ((DoubleConstant) right).Value; else if (left is FloatConstant) - bool_res = ((FloatConstant) left).Value < - ((FloatConstant) right).Value; + bool_res = ((FloatConstant) left).DoubleValue < + ((FloatConstant) right).DoubleValue; else if (left is ULongConstant) bool_res = ((ULongConstant) left).Value < ((ULongConstant) right).Value; @@ -1051,11 +1092,7 @@ namespace Mono.CSharp { if (left is NullLiteral) { var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); lifted_int.ResolveAsType (ec); - return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec); - } - - if (left is Nullable.LiftedNull) { - return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right).Resolve (ec); + return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec); } } @@ -1067,8 +1104,8 @@ namespace Mono.CSharp { bool_res = ((DoubleConstant) left).Value > ((DoubleConstant) right).Value; else if (left is FloatConstant) - bool_res = ((FloatConstant) left).Value > - ((FloatConstant) right).Value; + bool_res = ((FloatConstant) left).DoubleValue > + ((FloatConstant) right).DoubleValue; else if (left is ULongConstant) bool_res = ((ULongConstant) left).Value > ((ULongConstant) right).Value; @@ -1091,11 +1128,7 @@ namespace Mono.CSharp { if (left is NullLiteral) { var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); lifted_int.ResolveAsType (ec); - return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec); - } - - if (left is Nullable.LiftedNull) { - return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right).Resolve (ec); + return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec); } } @@ -1107,8 +1140,8 @@ namespace Mono.CSharp { bool_res = ((DoubleConstant) left).Value >= ((DoubleConstant) right).Value; else if (left is FloatConstant) - bool_res = ((FloatConstant) left).Value >= - ((FloatConstant) right).Value; + bool_res = ((FloatConstant) left).DoubleValue >= + ((FloatConstant) right).DoubleValue; else if (left is ULongConstant) bool_res = ((ULongConstant) left).Value >= ((ULongConstant) right).Value; @@ -1131,11 +1164,7 @@ namespace Mono.CSharp { if (left is NullLiteral) { var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); lifted_int.ResolveAsType (ec); - return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec); - } - - if (left is Nullable.LiftedNull) { - return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right).Resolve (ec); + return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec); } } @@ -1147,8 +1176,8 @@ namespace Mono.CSharp { bool_res = ((DoubleConstant) left).Value <= ((DoubleConstant) right).Value; else if (left is FloatConstant) - bool_res = ((FloatConstant) left).Value <= - ((FloatConstant) right).Value; + bool_res = ((FloatConstant) left).DoubleValue <= + ((FloatConstant) right).DoubleValue; else if (left is ULongConstant) bool_res = ((ULongConstant) left).Value <= ((ULongConstant) right).Value; @@ -1166,7 +1195,7 @@ namespace Mono.CSharp { return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location); } - + return null; } }