X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fconstant.cs;h=4030080a0b273504b59c05e496bd60cad8b91fb6;hb=e7690bd882ef9b0b077a0d15f4a7ec7d71ecfc70;hp=8cf943a1a5149d1f7bc09a6fc83906f822c2708f;hpb=666ddd999b99167b9acf6e0dba297208633ebe27;p=mono.git diff --git a/mcs/mcs/constant.cs b/mcs/mcs/constant.cs index 8cf943a1a51..4030080a0b2 100755 --- a/mcs/mcs/constant.cs +++ b/mcs/mcs/constant.cs @@ -11,17 +11,12 @@ namespace Mono.CSharp { using System; + using System.Reflection.Emit; /// /// Base class for constants and literals. /// public abstract class Constant : Expression { - - protected Constant () - { - eclass = ExprClass.Value; - } - /// /// This is different from ToString in that ToString /// is supposed to be there for debugging purposes, @@ -34,7 +29,7 @@ namespace Mono.CSharp { override public string ToString () { - return AsString (); + return this.GetType ().Name + " (" + AsString () + ")"; } /// @@ -42,7 +37,938 @@ namespace Mono.CSharp { /// cast into an object. /// public abstract object GetValue (); + + /// + /// Constants are always born in a fully resolved state + /// + public override Expression DoResolve (EmitContext ec) + { + return this; + } + + // + // The various ToXXXX conversion functions are used by the constant + // folding evaluator. A null value is returned if the conversion is + // not possible. + // + // Note: not all the patterns for catching `implicit_conv' are the same. + // some implicit conversions can never be performed between two types + // even if the conversion would be lossless (for example short to uint), + // but some conversions are explicitly permitted by the standard provided + // that there will be no loss of information (for example, int to uint). + // + public DoubleConstant ToDouble (Location loc) + { + DoubleConstant c = ConvertToDouble (); + + if (c == null) + Error_CannotConvertImplicit (loc, Type, TypeManager.double_type); + + return c; + } + + public FloatConstant ToFloat (Location loc) + { + FloatConstant c = ConvertToFloat (); + + if (c == null) + Error_CannotConvertImplicit (loc, Type, TypeManager.float_type); + + return c; + } + + public ULongConstant ToULong (Location loc) + { + ULongConstant c = ConvertToULong (); + + if (c == null) + Error_CannotConvertImplicit (loc, Type, TypeManager.uint64_type); + + return c; + } + + public LongConstant ToLong (Location loc) + { + LongConstant c = ConvertToLong (); + + if (c == null) + Error_CannotConvertImplicit (loc, Type, TypeManager.int64_type); + + return c; + } + + public UIntConstant ToUInt (Location loc) + { + UIntConstant c = ConvertToUInt (); + + if (c == null) + Error_CannotConvertImplicit (loc, Type, TypeManager.uint32_type); + + return c; + } + + public IntConstant ToInt (Location loc) + { + IntConstant c = ConvertToInt (); + + if (c == null) + Error_CannotConvertImplicit (loc, Type, TypeManager.int32_type); + + return c; + } + + public virtual DoubleConstant ConvertToDouble () + { + return null; + } + + public virtual FloatConstant ConvertToFloat () + { + return null; + } + + public virtual ULongConstant ConvertToULong () + { + return null; + } + + public virtual LongConstant ConvertToLong () + { + return null; + } + + public virtual UIntConstant ConvertToUInt () + { + return null; + } + + public virtual IntConstant ConvertToInt () + { + return null; + } + } + + public class BoolConstant : Constant { + public readonly bool Value; + + public BoolConstant (bool val) + { + type = TypeManager.bool_type; + eclass = ExprClass.Value; + + Value = val; + } + + override public string AsString () + { + return Value ? "true" : "false"; + } + + public override object GetValue () + { + return (object) Value; + } + + + public override void Emit (EmitContext ec) + { + if (Value) + ec.ig.Emit (OpCodes.Ldc_I4_1); + else + ec.ig.Emit (OpCodes.Ldc_I4_0); + } + } + + public class ByteConstant : Constant { + public readonly byte Value; + + public ByteConstant (byte v) + { + type = TypeManager.byte_type; + eclass = ExprClass.Value; + Value = v; + } + + public override void Emit (EmitContext ec) + { + IntLiteral.EmitInt (ec.ig, Value); + } + + public override string AsString () + { + return Value.ToString (); + } + + public override object GetValue () + { + return Value; + } + + public override DoubleConstant ConvertToDouble () + { + return new DoubleConstant (Value); + } + + public override FloatConstant ConvertToFloat () + { + return new FloatConstant (Value); + } + + public override ULongConstant ConvertToULong () + { + return new ULongConstant (Value); + } + + public override LongConstant ConvertToLong () + { + return new LongConstant (Value); + } + + public override UIntConstant ConvertToUInt () + { + return new UIntConstant (Value); + } + + public override IntConstant ConvertToInt () + { + return new IntConstant (Value); + } } + + public class CharConstant : Constant { + public readonly char Value; + + public CharConstant (char v) + { + type = TypeManager.char_type; + eclass = ExprClass.Value; + Value = v; + } + + public override void Emit (EmitContext ec) + { + IntLiteral.EmitInt (ec.ig, Value); + } + + static public string descape (char c) + { + switch (c){ + case '\a': + return "\\a"; + case '\b': + return "\\b"; + case '\n': + return "\\n"; + case '\t': + return "\\t"; + case '\v': + return "\\v"; + case '\r': + return "\\r"; + case '\\': + return "\\\\"; + case '\f': + return "\\f"; + case '\0': + return "\\0"; + case '"': + return "\\\""; + case '\'': + return "\\\'"; + } + return c.ToString (); + } + + public override string AsString () + { + return "\"" + descape (Value) + "\""; + } + + public override object GetValue () + { + return Value; + } + + public override DoubleConstant ConvertToDouble () + { + return new DoubleConstant (Value); + } + + public override FloatConstant ConvertToFloat () + { + return new FloatConstant (Value); + } + + public override ULongConstant ConvertToULong () + { + return new ULongConstant (Value); + } + + public override LongConstant ConvertToLong () + { + return new LongConstant (Value); + } + + public override UIntConstant ConvertToUInt () + { + return new UIntConstant (Value); + } + + public override IntConstant ConvertToInt () + { + return new IntConstant (Value); + } + } + + public class SByteConstant : Constant { + public readonly sbyte Value; + + public SByteConstant (sbyte v) + { + type = TypeManager.sbyte_type; + eclass = ExprClass.Value; + Value = v; + } + + public override void Emit (EmitContext ec) + { + IntLiteral.EmitInt (ec.ig, Value); + } + + public override string AsString () + { + return Value.ToString (); + } + + public override object GetValue () + { + return Value; + } + + public override DoubleConstant ConvertToDouble () + { + return new DoubleConstant (Value); + } + + public override FloatConstant ConvertToFloat () + { + return new FloatConstant (Value); + } + + public override ULongConstant ConvertToULong () + { + if (Value >= 0) + return new ULongConstant ((ulong) Value); + + return null; + } + + public override LongConstant ConvertToLong () + { + return new LongConstant (Value); + } + + public override UIntConstant ConvertToUInt () + { + return null; + } + + public override IntConstant ConvertToInt () + { + return new IntConstant (Value); + } + } + + public class ShortConstant : Constant { + public readonly short Value; + + public ShortConstant (short v) + { + type = TypeManager.short_type; + eclass = ExprClass.Value; + Value = v; + } + + public override void Emit (EmitContext ec) + { + IntLiteral.EmitInt (ec.ig, Value); + } + + public override string AsString () + { + return Value.ToString (); + } + + public override object GetValue () + { + return Value; + } + + public override DoubleConstant ConvertToDouble () + { + return new DoubleConstant (Value); + } + + public override FloatConstant ConvertToFloat () + { + return new FloatConstant (Value); + } + + public override ULongConstant ConvertToULong () + { + return null; + } + + public override LongConstant ConvertToLong () + { + return new LongConstant (Value); + } + + public override UIntConstant ConvertToUInt () + { + return null; + } + + public override IntConstant ConvertToInt () + { + return new IntConstant (Value); + } + } + + public class UShortConstant : Constant { + public readonly ushort Value; + + public UShortConstant (ushort v) + { + type = TypeManager.ushort_type; + eclass = ExprClass.Value; + Value = v; + } + + public override void Emit (EmitContext ec) + { + IntLiteral.EmitInt (ec.ig, Value); + } + + public override string AsString () + { + return Value.ToString (); + } + + public override object GetValue () + { + return Value; + } + + public override DoubleConstant ConvertToDouble () + { + return new DoubleConstant (Value); + } + + public override FloatConstant ConvertToFloat () + { + return new FloatConstant (Value); + } + + public override ULongConstant ConvertToULong () + { + return new ULongConstant (Value); + } + + public override LongConstant ConvertToLong () + { + return new LongConstant (Value); + } + + public override UIntConstant ConvertToUInt () + { + return new UIntConstant (Value); + } + + public override IntConstant ConvertToInt () + { + return new IntConstant (Value); + } + } + + public class IntConstant : Constant { + public readonly int Value; + + public IntConstant (int v) + { + type = TypeManager.int32_type; + eclass = ExprClass.Value; + Value = v; + } + + static public void EmitInt (ILGenerator ig, int i) + { + switch (i){ + case -1: + ig.Emit (OpCodes.Ldc_I4_M1); + break; + + case 0: + ig.Emit (OpCodes.Ldc_I4_0); + break; + + case 1: + ig.Emit (OpCodes.Ldc_I4_1); + break; + + case 2: + ig.Emit (OpCodes.Ldc_I4_2); + break; + + case 3: + ig.Emit (OpCodes.Ldc_I4_3); + break; + + case 4: + ig.Emit (OpCodes.Ldc_I4_4); + break; + + case 5: + ig.Emit (OpCodes.Ldc_I4_5); + break; + + case 6: + ig.Emit (OpCodes.Ldc_I4_6); + break; + + case 7: + ig.Emit (OpCodes.Ldc_I4_7); + break; + + case 8: + ig.Emit (OpCodes.Ldc_I4_8); + break; + + default: + if (i >= -128 && i <= 127){ + ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i); + } else + ig.Emit (OpCodes.Ldc_I4, i); + break; + } + } + + public override void Emit (EmitContext ec) + { + EmitInt (ec.ig, Value); + } + + public override string AsString () + { + return Value.ToString (); + } + + public override object GetValue () + { + return Value; + } + + public override DoubleConstant ConvertToDouble () + { + return new DoubleConstant (Value); + } + + public override FloatConstant ConvertToFloat () + { + return new FloatConstant (Value); + } + + public override ULongConstant ConvertToULong () + { + if (Value < 0) + return null; + + return new ULongConstant ((ulong) Value); + } + + public override LongConstant ConvertToLong () + { + return new LongConstant (Value); + } + + public override UIntConstant ConvertToUInt () + { + if (Value < 0) + return null; + + return new UIntConstant ((uint) Value); + } + + public override IntConstant ConvertToInt () + { + return this; + } + } + + public class UIntConstant : Constant { + public readonly uint Value; + + public UIntConstant (uint v) + { + type = TypeManager.uint32_type; + eclass = ExprClass.Value; + Value = v; + } + + public override void Emit (EmitContext ec) + { + IntLiteral.EmitInt (ec.ig, unchecked ((int) Value)); + } + + public override string AsString () + { + return Value.ToString (); + } + + public override object GetValue () + { + return Value; + } + + public override DoubleConstant ConvertToDouble () + { + return new DoubleConstant (Value); + } + + public override FloatConstant ConvertToFloat () + { + return new FloatConstant (Value); + } + + public override ULongConstant ConvertToULong () + { + return new ULongConstant (Value); + } + + public override LongConstant ConvertToLong () + { + return new LongConstant (Value); + } + + public override UIntConstant ConvertToUInt () + { + return this; + } + + public override IntConstant ConvertToInt () + { + return null; + } + } + + public class LongConstant : Constant { + public readonly long Value; + + public LongConstant (long v) + { + type = TypeManager.int64_type; + eclass = ExprClass.Value; + Value = v; + } + + public override void Emit (EmitContext ec) + { + ILGenerator ig = ec.ig; + + EmitLong (ig, Value); + } + + static public void EmitLong (ILGenerator ig, long l) + { + if ((l >> 32) == 0){ + IntLiteral.EmitInt (ig, unchecked ((int) l)); + ig.Emit (OpCodes.Conv_U8); + } else { + ig.Emit (OpCodes.Ldc_I8, l); + } + } + + public override string AsString () + { + return Value.ToString (); + } + + public override object GetValue () + { + return Value; + } + + public override DoubleConstant ConvertToDouble () + { + return new DoubleConstant (Value); + } + + public override FloatConstant ConvertToFloat () + { + return new FloatConstant (Value); + } + + public override ULongConstant ConvertToULong () + { + if (Value < 0) + return null; + + return new ULongConstant ((ulong) Value); + } + + public override LongConstant ConvertToLong () + { + return this; + } + + public override UIntConstant ConvertToUInt () + { + return null; + } + + public override IntConstant ConvertToInt () + { + return null; + } + } + + public class ULongConstant : Constant { + public readonly ulong Value; + + public ULongConstant (ulong v) + { + type = TypeManager.uint64_type; + eclass = ExprClass.Value; + Value = v; + } + + public override void Emit (EmitContext ec) + { + ILGenerator ig = ec.ig; + + LongLiteral.EmitLong (ig, unchecked ((long) Value)); + } + + public override string AsString () + { + return Value.ToString (); + } + + public override object GetValue () + { + return Value; + } + + public override DoubleConstant ConvertToDouble () + { + return new DoubleConstant (Value); + } + + public override FloatConstant ConvertToFloat () + { + return new FloatConstant (Value); + } + + public override ULongConstant ConvertToULong () + { + return this; + } + + public override LongConstant ConvertToLong () + { + return null; + } + + public override UIntConstant ConvertToUInt () + { + return null; + } + + public override IntConstant ConvertToInt () + { + return null; + } + } + + public class FloatConstant : Constant { + public readonly float Value; + + public FloatConstant (float v) + { + type = TypeManager.float_type; + eclass = ExprClass.Value; + Value = v; + } + + public override void Emit (EmitContext ec) + { + ec.ig.Emit (OpCodes.Ldc_R4, Value); + } + + public override string AsString () + { + return Value.ToString (); + } + + public override object GetValue () + { + return Value; + } + + public override DoubleConstant ConvertToDouble () + { + return new DoubleConstant (Value); + } + + public override FloatConstant ConvertToFloat () + { + return this; + } + + public override LongConstant ConvertToLong () + { + return null; + } + + public override UIntConstant ConvertToUInt () + { + return null; + } + + public override IntConstant ConvertToInt () + { + return null; + } + } + + public class DoubleConstant : Constant { + public readonly double Value; + + public DoubleConstant (double v) + { + type = TypeManager.double_type; + eclass = ExprClass.Value; + Value = v; + } + + public override void Emit (EmitContext ec) + { + ec.ig.Emit (OpCodes.Ldc_R8, Value); + } + + public override string AsString () + { + return Value.ToString (); + } + + public override object GetValue () + { + return Value; + } + + public override DoubleConstant ConvertToDouble () + { + return this; + } + + public override FloatConstant ConvertToFloat () + { + return null; + } + + public override ULongConstant ConvertToULong () + { + return null; + } + + public override LongConstant ConvertToLong () + { + return null; + } + + public override UIntConstant ConvertToUInt () + { + return null; + } + + public override IntConstant ConvertToInt () + { + return null; + } + } + + public class DecimalConstant : Constant { + public readonly decimal Value; + + public DecimalConstant (decimal d) + { + type = TypeManager.decimal_type; + eclass = ExprClass.Value; + Value = d; + } + + override public string AsString () + { + return Value.ToString (); + } + + public override object GetValue () + { + return (object) Value; + } + + public override void Emit (EmitContext ec) + { + int [] words = Decimal.GetBits (Value); + + // + // FIXME: we could optimize this, and call a better + // constructor + // + + ILGenerator ig = ec.ig; + + IntConstant.EmitInt (ig, words [0]); + IntConstant.EmitInt (ig, words [1]); + IntConstant.EmitInt (ig, words [2]); + + // sign + IntConstant.EmitInt (ig, words [3] >> 31); + + // power + IntConstant.EmitInt (ig, (words [3] >> 16) & 0xff); + + ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args); + } + } + + public class StringConstant : Constant { + public readonly string Value; + + public StringConstant (string s) + { + type = TypeManager.string_type; + eclass = ExprClass.Value; + Value = s; + } + + // FIXME: Escape the string. + override public string AsString () + { + return "\"" + Value + "\""; + } + + public override object GetValue () + { + return Value; + } + + public override void Emit (EmitContext ec) + { + ec.ig.Emit (OpCodes.Ldstr, Value); + } + } + }