X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fcfold.cs;h=47c76af3ed8226bbd8f83f21404ba0cb4aecb1d1;hb=109bb0350beed07567ae9d5e9aa26e0d37e05342;hp=2d3c96942aa8d842996751643355a132c288650a;hpb=28776e66837c35ad00ca409831350697af055b78;p=mono.git diff --git a/mcs/mcs/cfold.cs b/mcs/mcs/cfold.cs old mode 100755 new mode 100644 index 2d3c96942aa..47c76af3ed8 --- a/mcs/mcs/cfold.cs +++ b/mcs/mcs/cfold.cs @@ -3,16 +3,21 @@ // // 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'. @@ -20,172 +25,43 @@ namespace Mono.CSharp { // 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) - // (short, short) (Happens with enumerations with underlying short type) - // (ushort, ushort) (Happens with enumerations with underlying short type) - // - 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); - - 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 - // -#if WRONG - Constant match, other; -#endif - - if (left is ULongConstant){ -#if WRONG - other = right; - match = left; -#endif - if (!(right is ULongConstant)) - right = right.ToULong (loc); - } else { -#if WRONG - other = left; - match = right; -#endif - 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 other; - if (left is UIntConstant) - other = right; - else - other = left; - - // Nothing to do. - if (other is UIntConstant) - return; - - IntConstant ic = other as IntConstant; - if (ic != null){ - if (ic.Value >= 0){ - if (left == other) - left = new UIntConstant ((uint) ic.Value); - else - right = new UIntConstant ((uint) ic.Value); - return; - } - } - - if (other is SByteConstant || other is ShortConstant || ic != null){ - left = left.ToLong (loc); - right = right.ToLong (loc); - } else { - left = left.ToUInt (loc); - right = left.ToUInt (loc); - } + Type ltype = left.Type; + Type rtype = right.Type; - return; - } else if (left is DecimalConstant || right is DecimalConstant) { - if (!(left is DecimalConstant)) - left = left.ToDecimal (loc); - else if (!(right is DecimalConstant)) - 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; - } + foreach (Type t in binary_promotions) { + if (t == ltype) + return t == rtype || ConvertPromotion (ref right, ref left, t); - 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"); } @@ -195,22 +71,58 @@ namespace Mono.CSharp { /// /// Returns null if the expression can not be folded. /// - 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) @@ -218,248 +130,177 @@ namespace Mono.CSharp { 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); - } else if (left is UShortConstant){ - UShortConstant v; - ushort res = (ushort) (((UShortConstant)left).Value | - ((UShortConstant)right).Value); - - v = new UShortConstant (res); - if (result_type == null) - return v; - else - return new EnumConstant (v, result_type); - } else if (left is ShortConstant){ - ShortConstant v; - short res = (short) (((ShortConstant)left).Value | - ((ShortConstant)right).Value); - - v = new ShortConstant (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); - } else if (left is UShortConstant){ - UShortConstant v; - ushort res = (ushort) (((UShortConstant)left).Value & - ((UShortConstant)right).Value); - - v = new UShortConstant (res); - if (result_type == null) - return v; - else - return new EnumConstant (v, result_type); - } else if (left is ShortConstant){ - ShortConstant v; - short res = (short) (((ShortConstant)left).Value & - ((ShortConstant)right).Value); - - v = new ShortConstant (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); - } else if (left is UShortConstant){ - UShortConstant v; - ushort res = (ushort) (((UShortConstant)left).Value ^ - ((UShortConstant)right).Value); - - v = new UShortConstant (res); - if (result_type == null) - return v; - else - return new EnumConstant (v, result_type); - } else if (left is ShortConstant){ - ShortConstant v; - short res = (short)(((ShortConstant)left).Value ^ - ((ShortConstant)right).Value); - - v = new ShortConstant (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; + + 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); } - result = null; - DoConstantNumericPromotions (ec, oper, ref left, ref right, loc); - if (left == null || right == null) + if (!DoBinaryNumericPromotions (ref left, ref right)) return null; try { @@ -473,8 +314,9 @@ namespace Mono.CSharp { 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) @@ -484,7 +326,7 @@ namespace Mono.CSharp { 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; @@ -495,7 +337,7 @@ namespace Mono.CSharp { 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; @@ -506,7 +348,7 @@ namespace Mono.CSharp { 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; @@ -517,7 +359,7 @@ namespace Mono.CSharp { 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; @@ -528,7 +370,18 @@ namespace Mono.CSharp { 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 addition input: " + left); } @@ -536,37 +389,39 @@ namespace Mono.CSharp { 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 { @@ -580,7 +435,7 @@ namespace Mono.CSharp { 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; @@ -591,7 +446,7 @@ namespace Mono.CSharp { 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; @@ -602,7 +457,7 @@ namespace Mono.CSharp { 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; @@ -613,7 +468,7 @@ namespace Mono.CSharp { 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; @@ -624,7 +479,7 @@ namespace Mono.CSharp { 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; @@ -635,21 +490,29 @@ namespace Mono.CSharp { 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 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 { @@ -663,7 +526,7 @@ namespace Mono.CSharp { 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; @@ -674,7 +537,7 @@ namespace Mono.CSharp { 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; @@ -685,7 +548,7 @@ namespace Mono.CSharp { 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; @@ -696,7 +559,7 @@ namespace Mono.CSharp { 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; @@ -707,7 +570,7 @@ namespace Mono.CSharp { 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; @@ -718,7 +581,7 @@ namespace Mono.CSharp { res = unchecked (((IntConstant) left).Value * ((IntConstant) right).Value); - return new IntConstant (res); + return new IntConstant (res, left.Location); } else if (left is DecimalConstant) { decimal res; @@ -729,7 +592,7 @@ namespace Mono.CSharp { res = unchecked (((DecimalConstant) left).Value * ((DecimalConstant) right).Value); - return new DecimalConstant (res); + return new DecimalConstant (res, left.Location); } else { throw new Exception ( "Unexepected multiply input: " + left); } @@ -739,8 +602,7 @@ namespace Mono.CSharp { 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 { @@ -754,7 +616,7 @@ namespace Mono.CSharp { 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; @@ -765,7 +627,7 @@ namespace Mono.CSharp { 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; @@ -776,7 +638,7 @@ namespace Mono.CSharp { 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; @@ -787,7 +649,7 @@ namespace Mono.CSharp { 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; @@ -798,7 +660,7 @@ namespace Mono.CSharp { 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; @@ -809,7 +671,7 @@ namespace Mono.CSharp { res = unchecked (((IntConstant) left).Value / ((IntConstant) right).Value); - return new IntConstant (res); + return new IntConstant (res, left.Location); } else if (left is DecimalConstant) { decimal res; @@ -820,7 +682,7 @@ namespace Mono.CSharp { res = unchecked (((DecimalConstant) left).Value / ((DecimalConstant) right).Value); - return new DecimalConstant (res); + return new DecimalConstant (res, left.Location); } else { throw new Exception ( "Unexepected division input: " + left); } @@ -834,8 +696,7 @@ namespace Mono.CSharp { 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 { @@ -849,7 +710,7 @@ namespace Mono.CSharp { 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; @@ -860,7 +721,7 @@ namespace Mono.CSharp { 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; @@ -871,7 +732,7 @@ namespace Mono.CSharp { 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; @@ -882,7 +743,7 @@ namespace Mono.CSharp { 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; @@ -893,7 +754,7 @@ namespace Mono.CSharp { 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; @@ -904,7 +765,7 @@ namespace Mono.CSharp { res = unchecked (((IntConstant) left).Value % ((IntConstant) right).Value); - return new IntConstant (res); + return new IntConstant (res, left.Location); } else { throw new Exception ( "Unexepected modulus input: " + left); } @@ -919,107 +780,73 @@ namespace Mono.CSharp { // 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); + 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.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 NullLiteral){ if (right is NullLiteral) - return new BoolConstant (true); + return new BoolConstant (true, left.Location); else if (right is StringConstant) return new BoolConstant ( - ((StringConstant) right).Value == null); - } else if (right is NullLiteral){ + ((StringConstant) right).Value == null, left.Location); + } else if (right is NullLiteral) { if (left is NullLiteral) - return new BoolConstant (true); + return new BoolConstant (true, left.Location); else if (left is StringConstant) return new BoolConstant ( - ((StringConstant) left).Value == null); + ((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; @@ -1044,35 +871,30 @@ namespace Mono.CSharp { 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 (left is NullLiteral) { if (right is NullLiteral) - return new BoolConstant (false); + return new BoolConstant (false, left.Location); else if (right is StringConstant) return new BoolConstant ( - ((StringConstant) right).Value != null); - } else if (right is NullLiteral){ + ((StringConstant) right).Value != null, left.Location); + } else if (right is NullLiteral) { if (left is NullLiteral) - return new BoolConstant (false); + return new BoolConstant (false, left.Location); else if (left is StringConstant) return new BoolConstant ( - ((StringConstant) left).Value != null); + ((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; @@ -1097,11 +919,10 @@ namespace Mono.CSharp { 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; @@ -1126,11 +947,10 @@ namespace Mono.CSharp { 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; @@ -1155,11 +975,10 @@ namespace Mono.CSharp { 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; @@ -1184,11 +1003,10 @@ namespace Mono.CSharp { 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; @@ -1213,7 +1031,7 @@ namespace Mono.CSharp { else return null; - return new BoolConstant (bool_res); + return new BoolConstant (bool_res, left.Location); } return null;