📄 cfold.cs
字号:
//// cfold.cs: Constant Folding//// Author:// Miguel de Icaza (miguel@ximian.com)//// (C) 2002, 2003 Ximian, Inc.//using System;namespace Mono.CSharp { public class ConstantFold { // // Performs the numeric promotions on the left and right expresions // and desposits the results on `lc' and `rc'. // // On success, the types of `lc' and `rc' on output will always match, // and the pair will be one of: // // (double, double) // (float, float) // (ulong, ulong) // (long, long) // (uint, uint) // (int, int) // (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) { 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, ic.Location); else right = new UIntConstant ((uint) ic.Value, ic.Location); 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); } 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 (left is EnumConstant) left = ((EnumConstant) left).Child; if (right is EnumConstant) right = ((EnumConstant) right).Child; DoConstantNumericPromotions (ec, oper, ref left, ref right, loc); return; } else { // // Force conversions to int32 // if (!(left is IntConstant)) left = left.ToInt (loc); if (!(right is IntConstant)) right = right.ToInt (loc); } return; } static void Error_CompileTimeOverflow (Location loc) { Report.Error (220, loc, "The operation overflows at compile time in checked mode"); } /// <summary> /// Constant expression folder for binary operations. /// /// Returns null if the expression can not be folded. /// </summary> static public Expression BinaryFold (EmitContext ec, Binary.Operator oper, Constant left, Constant right, Location loc) { 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; bool bool_res; // // Enumerator folding // if (rt == lt && left is EnumConstant) result_type = lt; // // During an enum evaluation, we need to unwrap enumerations // if (ec.InEnumContext){ if (left is EnumConstant) left = ((EnumConstant) left).Child; if (right is EnumConstant) right = ((EnumConstant) right).Child; } Type wrap_as; Constant result = null; switch (oper){ case Binary.Operator.BitwiseOr: DoConstantNumericPromotions (ec, oper, ref left, ref right, loc); if (left == null || right == null) return null; if (left is IntConstant){ IntConstant v; int res = ((IntConstant) left).Value | ((IntConstant) right).Value; v = new IntConstant (res, left.Location); if (result_type == null) return v; else return new EnumConstant (v, result_type); } else if (left is UIntConstant){ UIntConstant v; uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value; v = new UIntConstant (res, left.Location); if (result_type == null) return v; else return new EnumConstant (v, result_type); } else if (left is LongConstant){ LongConstant v; long res = ((LongConstant)left).Value | ((LongConstant)right).Value; v = new LongConstant (res, left.Location); if (result_type == null) return v; else return new EnumConstant (v, result_type); } else if (left is ULongConstant){ ULongConstant v; ulong res = ((ULongConstant)left).Value | ((ULongConstant)right).Value; v = new ULongConstant (res, left.Location); 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, left.Location); 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, left.Location); if (result_type == null) return v; else return new EnumConstant (v, result_type); } break; case Binary.Operator.BitwiseAnd: DoConstantNumericPromotions (ec, oper, ref left, ref right, loc); if (left == null || right == null) return null; if (left is IntConstant){ IntConstant v; int res = ((IntConstant) left).Value & ((IntConstant) right).Value; v = new IntConstant (res, left.Location); if (result_type == null) return v; else return new EnumConstant (v, result_type); } else if (left is UIntConstant){ UIntConstant v; uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value; v = new UIntConstant (res, left.Location); if (result_type == null) return v; else return new EnumConstant (v, result_type); } else if (left is LongConstant){ LongConstant v; long res = ((LongConstant)left).Value & ((LongConstant)right).Value; v = new LongConstant (res, left.Location); if (result_type == null) return v; else return new EnumConstant (v, result_type); } else if (left is ULongConstant){ ULongConstant v; ulong res = ((ULongConstant)left).Value & ((ULongConstant)right).Value; v = new ULongConstant (res, left.Location); 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, left.Location); 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, left.Location); if (result_type == null) return v; else return new EnumConstant (v, result_type); } break; case Binary.Operator.ExclusiveOr: DoConstantNumericPromotions (ec, oper, ref left, ref right, loc); if (left == null || right == null) return null; if (left is IntConstant){ IntConstant v; int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value; v = new IntConstant (res, left.Location); if (result_type == null) return v; else return new EnumConstant (v, result_type); } else if (left is UIntConstant){ UIntConstant v; uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value; v = new UIntConstant (res, left.Location); if (result_type == null) return v; else return new EnumConstant (v, result_type); } else if (left is LongConstant){ LongConstant v; long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value; v = new LongConstant (res, left.Location); if (result_type == null) return v; else return new EnumConstant (v, result_type); } else if (left is ULongConstant){ ULongConstant v; ulong res = ((ULongConstant)left).Value ^ ((ULongConstant)right).Value; v = new ULongConstant (res, left.Location); 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, left.Location); 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, left.Location); if (result_type == null) return v; else return new EnumConstant (v, result_type); } break; case Binary.Operator.Addition: bool left_is_string = left is StringConstant; bool right_is_string = right is StringConstant; // // If both sides are strings, then concatenate, if // one is a string, and the other is not, then defer // to runtime concatenation // wrap_as = null; if (left_is_string || right_is_string){ if (left_is_string && right_is_string) return new StringConstant ( ((StringConstant) left).Value +
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -