X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fconstant.cs;h=81d2c9604c33482226971554f6c8f736937bc64d;hb=3204e13673602e695cfaf5520ae45440dcb006ed;hp=f4cd14603d62f3101be74d2640982785b70b71ec;hpb=07d69753d509f305d975819ffa4c803e2b1bcc12;p=mono.git diff --git a/mcs/mcs/constant.cs b/mcs/mcs/constant.cs index f4cd14603d6..81d2c9604c3 100644 --- a/mcs/mcs/constant.cs +++ b/mcs/mcs/constant.cs @@ -10,7 +10,12 @@ // using System; + +#if STATIC +using IKVM.Reflection.Emit; +#else using System.Reflection.Emit; +#endif namespace Mono.CSharp { @@ -24,36 +29,9 @@ namespace Mono.CSharp { this.loc = loc; } - /// - /// This is different from ToString in that ToString - /// is supposed to be there for debugging purposes, - /// and is not guaranteed to be useful for anything else, - /// AsString() will provide something that can be used - /// for round-tripping C# code. Maybe it can be used - /// for IL assembly as well. - /// - public abstract string AsString (); - override public string ToString () { - return this.GetType ().Name + " (" + AsString () + ")"; - } - - public override bool GetAttributableValue (ResolveContext ec, Type value_type, out object value) - { - if (value_type == TypeManager.object_type) { - value = GetTypedValue (); - return true; - } - - Constant c = ImplicitConversionRequired (ec, value_type, loc); - if (c == null) { - value = null; - return false; - } - - value = c.GetTypedValue (); - return true; + return this.GetType ().Name + " (" + GetValueAsLiteral () + ")"; } /// @@ -62,24 +40,31 @@ namespace Mono.CSharp { /// public abstract object GetValue (); + public abstract string GetValueAsLiteral (); + +#if !STATIC + // + // Returns an object value which is typed to contant type + // public virtual object GetTypedValue () { return GetValue (); } +#endif - public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, Type target, bool expl) + public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) { if (!expl && IsLiteral && (TypeManager.IsPrimitiveType (target) || type == TypeManager.decimal_type) && (TypeManager.IsPrimitiveType (type) || type == TypeManager.decimal_type)) { ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'", - AsString (), TypeManager.CSharpName (target)); + GetValueAsLiteral (), TypeManager.CSharpName (target)); } else { base.Error_ValueCannotBeConverted (ec, loc, target, expl); } } - public Constant ImplicitConversionRequired (ResolveContext ec, Type type, Location loc) + public Constant ImplicitConversionRequired (ResolveContext ec, TypeSpec type, Location loc) { Constant c = ConvertImplicitly (ec, type); if (c == null) @@ -88,7 +73,7 @@ namespace Mono.CSharp { return c; } - public virtual Constant ConvertImplicitly (ResolveContext rc, Type type) + public virtual Constant ConvertImplicitly (ResolveContext rc, TypeSpec type) { if (this.type == type) return this; @@ -113,12 +98,12 @@ namespace Mono.CSharp { // // Returns a constant instance based on Type // - public static Constant CreateConstant (ResolveContext rc, Type t, object v, Location loc) + public static Constant CreateConstant (ResolveContext rc, TypeSpec t, object v, Location loc) { return CreateConstantFromValue (t, v, loc).Resolve (rc); } - public static Constant CreateConstantFromValue (Type t, object v, Location loc) + public static Constant CreateConstantFromValue (TypeSpec t, object v, Location loc) { if (t == TypeManager.int32_type) return new IntConstant ((int) v, loc); @@ -149,7 +134,7 @@ namespace Mono.CSharp { if (t == TypeManager.decimal_type) return new DecimalConstant ((decimal) v, loc); if (TypeManager.IsEnumType (t)) { - Type real_type = TypeManager.GetEnumUnderlyingType (t); + var real_type = EnumSpec.GetUnderlyingType (t); return new EnumConstant (CreateConstantFromValue (real_type, v, loc).Resolve (null), t); } if (v == null) { @@ -179,36 +164,37 @@ namespace Mono.CSharp { /// It throws OverflowException /// // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS - public abstract Constant ConvertExplicitly (bool in_checked_context, Type target_type); + public abstract Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type); /// /// Attempts to do a compile-time folding of a constant cast. /// - public Constant TryReduce (ResolveContext ec, Type target_type, Location loc) + public Constant TryReduce (ResolveContext ec, TypeSpec target_type, Location loc) { try { return TryReduce (ec, target_type); } catch (OverflowException) { - if (ec.ConstantCheckState) { - ec.Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)", - GetValue ().ToString (), TypeManager.CSharpName (target_type)); + if (ec.ConstantCheckState && Type.BuildinType != BuildinTypeSpec.Type.Decimal) { + ec.Report.Error (221, loc, + "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)", + GetValueAsLiteral (), target_type.GetSignatureForError ()); } else { Error_ValueCannotBeConverted (ec, loc, target_type, false); } - return New.Constantify (target_type).Resolve (ec); + return New.Constantify (target_type, loc).Resolve (ec); } } - Constant TryReduce (ResolveContext ec, Type target_type) + Constant TryReduce (ResolveContext ec, TypeSpec target_type) { if (Type == target_type) return this; Constant c; if (TypeManager.IsEnumType (target_type)) { - c = TryReduce (ec, TypeManager.GetEnumUnderlyingType (target_type)); + c = TryReduce (ec, EnumSpec.GetUnderlyingType (target_type)); if (c == null) return null; @@ -226,7 +212,7 @@ namespace Mono.CSharp { /// Need to pass type as the constant can require a boxing /// and in such case no optimization is possible /// - public bool IsDefaultInitializer (Type type) + public bool IsDefaultInitializer (TypeSpec type) { if (type == Type) return IsDefaultValue; @@ -248,6 +234,10 @@ namespace Mono.CSharp { public virtual bool IsLiteral { get { return false; } } + + public virtual bool IsOneInteger { + get { return false; } + } // // Returns true iff 1) the stack type of this is one of Object, @@ -262,19 +252,24 @@ namespace Mono.CSharp { // do nothing } - protected override void CloneTo (CloneContext clonectx, Expression target) + public sealed override Expression Clone (CloneContext clonectx) { - // CloneTo: Nothing, we do not keep any state on this expression + // No cloning is not needed for constants + return this; } - public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx) + protected override void CloneTo (CloneContext clonectx, Expression target) { - return System.Linq.Expressions.Expression.Constant (GetTypedValue (), type); + throw new NotSupportedException ("should not be reached"); } - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx) { - // A constant cannot be of generic type +#if STATIC + return base.MakeExpression (ctx); +#else + return System.Linq.Expressions.Expression.Constant (GetTypedValue (), type.GetMetaInfo ()); +#endif } public new Constant Resolve (ResolveContext rc) @@ -299,13 +294,14 @@ namespace Mono.CSharp { } } - public abstract class IntegralConstant : Constant { + public abstract class IntegralConstant : Constant + { protected IntegralConstant (Location loc) : base (loc) { } - public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, Type target, bool expl) + public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) { try { ConvertExplicitly (true, target); @@ -318,6 +314,11 @@ namespace Mono.CSharp { } } + public override string GetValueAsLiteral () + { + return GetValue ().ToString (); + } + public abstract Constant Increment (); } @@ -330,11 +331,6 @@ namespace Mono.CSharp { Value = val; } - override public string AsString () - { - return Value ? "true" : "false"; - } - protected override Expression DoResolve (ResolveContext ec) { type = TypeManager.bool_type; @@ -346,13 +342,23 @@ namespace Mono.CSharp { { return (object) Value; } + + public override string GetValueAsLiteral () + { + return Value ? "true" : "false"; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } public override void Emit (EmitContext ec) { if (Value) - ec.ig.Emit (OpCodes.Ldc_I4_1); + ec.Emit (OpCodes.Ldc_I4_1); else - ec.ig.Emit (OpCodes.Ldc_I4_0); + ec.Emit (OpCodes.Ldc_I4_0); } public override bool IsDefaultValue { @@ -371,7 +377,7 @@ namespace Mono.CSharp { get { return Value == false; } } - public override Constant ConvertExplicitly (bool in_checked_context, Type target_type) + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { return null; } @@ -387,14 +393,14 @@ namespace Mono.CSharp { Value = v; } - public override void Emit (EmitContext ec) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) { - IntLiteral.EmitInt (ec.ig, Value); + enc.Encode (Value); } - public override string AsString () + public override void Emit (EmitContext ec) { - return Value.ToString (); + ec.EmitInt (Value); } protected override Expression DoResolve (ResolveContext ec) @@ -420,6 +426,12 @@ namespace Mono.CSharp { } } + public override bool IsOneInteger { + get { + return Value == 1; + } + } + public override bool IsNegative { get { return false; @@ -430,7 +442,7 @@ namespace Mono.CSharp { get { return Value == 0; } } - public override Constant ConvertExplicitly (bool in_checked_context, Type target_type) + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { if (target_type == TypeManager.sbyte_type) { if (in_checked_context){ @@ -481,9 +493,14 @@ namespace Mono.CSharp { return this; } + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode ((ushort) Value); + } + public override void Emit (EmitContext ec) { - IntLiteral.EmitInt (ec.ig, Value); + ec.EmitInt (Value); } static string descape (char c) @@ -515,14 +532,14 @@ namespace Mono.CSharp { return c.ToString (); } - public override string AsString () + public override object GetValue () { - return "\"" + descape (Value) + "\""; + return Value; } - public override object GetValue () + public override string GetValueAsLiteral () { - return Value; + return "\"" + descape (Value) + "\""; } public override bool IsDefaultValue { @@ -541,7 +558,7 @@ namespace Mono.CSharp { get { return Value == '\0'; } } - public override Constant ConvertExplicitly (bool in_checked_context, Type target_type) + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { if (target_type == TypeManager.byte_type) { if (in_checked_context){ @@ -600,14 +617,14 @@ namespace Mono.CSharp { return this; } - public override void Emit (EmitContext ec) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) { - IntLiteral.EmitInt (ec.ig, Value); + enc.Encode (Value); } - public override string AsString () + public override void Emit (EmitContext ec) { - return Value.ToString (); + ec.EmitInt (Value); } public override object GetValue () @@ -632,11 +649,17 @@ namespace Mono.CSharp { } } + public override bool IsOneInteger { + get { + return Value == 1; + } + } + public override bool IsZeroInteger { get { return Value == 0; } } - public override Constant ConvertExplicitly (bool in_checked_context, Type target_type) + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { if (target_type == TypeManager.byte_type) { if (in_checked_context && Value < 0) @@ -695,14 +718,14 @@ namespace Mono.CSharp { return this; } - public override void Emit (EmitContext ec) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) { - IntLiteral.EmitInt (ec.ig, Value); + enc.Encode (Value); } - public override string AsString () + public override void Emit (EmitContext ec) { - return Value.ToString (); + ec.EmitInt (Value); } public override object GetValue () @@ -730,8 +753,14 @@ namespace Mono.CSharp { return Value < 0; } } + + public override bool IsOneInteger { + get { + return Value == 1; + } + } - public override Constant ConvertExplicitly (bool in_checked_context, Type target_type) + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { if (target_type == TypeManager.byte_type) { if (in_checked_context){ @@ -802,14 +831,14 @@ namespace Mono.CSharp { return this; } - public override void Emit (EmitContext ec) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) { - IntLiteral.EmitInt (ec.ig, Value); + enc.Encode (Value); } - public override string AsString () + public override void Emit (EmitContext ec) { - return Value.ToString (); + ec.EmitInt (Value); } public override object GetValue () @@ -833,12 +862,18 @@ namespace Mono.CSharp { return false; } } + + public override bool IsOneInteger { + get { + return Value == 1; + } + } public override bool IsZeroInteger { get { return Value == 0; } } - public override Constant ConvertExplicitly (bool in_checked_context, Type target_type) + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { if (target_type == TypeManager.byte_type) { if (in_checked_context){ @@ -903,66 +938,14 @@ namespace Mono.CSharp { return this; } - static public void EmitInt (ILGenerator ig, int i) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) { - 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; - } + enc.Encode (Value); } public override void Emit (EmitContext ec) { - EmitInt (ec.ig, Value); - } - - public override string AsString () - { - return Value.ToString (); + ec.EmitInt (Value); } public override object GetValue () @@ -986,12 +969,18 @@ namespace Mono.CSharp { return Value < 0; } } + + public override bool IsOneInteger { + get { + return Value == 1; + } + } public override bool IsZeroInteger { get { return Value == 0; } } - public override Constant ConvertExplicitly (bool in_checked_context, Type target_type) + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { if (target_type == TypeManager.byte_type) { if (in_checked_context){ @@ -1052,7 +1041,7 @@ namespace Mono.CSharp { return null; } - public override Constant ConvertImplicitly (ResolveContext rc, Type type) + public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec type) { if (this.type == type) return this; @@ -1069,7 +1058,7 @@ namespace Mono.CSharp { /// into a different data type using casts (See Implicit Constant /// Expression Conversions) /// - Constant TryImplicitIntConversion (Type target_type) + Constant TryImplicitIntConversion (TypeSpec target_type) { if (target_type == TypeManager.sbyte_type) { if (Value >= SByte.MinValue && Value <= SByte.MaxValue) @@ -1125,14 +1114,14 @@ namespace Mono.CSharp { return this; } - public override void Emit (EmitContext ec) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) { - IntLiteral.EmitInt (ec.ig, unchecked ((int) Value)); + enc.Encode (Value); } - public override string AsString () + public override void Emit (EmitContext ec) { - return Value.ToString (); + ec.EmitInt (unchecked ((int) Value)); } public override object GetValue () @@ -1156,16 +1145,22 @@ namespace Mono.CSharp { return false; } } + + public override bool IsOneInteger { + get { + return Value == 1; + } + } public override bool IsZeroInteger { get { return Value == 0; } } - public override Constant ConvertExplicitly (bool in_checked_context, Type target_type) + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { if (target_type == TypeManager.byte_type) { if (in_checked_context){ - if (Value < Char.MinValue || Value > Char.MaxValue) + if (Value < 0 || Value > byte.MaxValue) throw new OverflowException (); } return new ByteConstant ((byte) Value, Location); @@ -1237,31 +1232,14 @@ namespace Mono.CSharp { return this; } - public override void Emit (EmitContext ec) - { - EmitLong (ec.ig, Value); - } - - static public void EmitLong (ILGenerator ig, long l) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) { - if (l >= int.MinValue && l <= int.MaxValue) { - IntLiteral.EmitInt (ig, unchecked ((int) l)); - ig.Emit (OpCodes.Conv_I8); - return; - } - - if (l >= 0 && l <= uint.MaxValue) { - IntLiteral.EmitInt (ig, unchecked ((int) l)); - ig.Emit (OpCodes.Conv_U8); - return; - } - - ig.Emit (OpCodes.Ldc_I8, l); + enc.Encode (Value); } - public override string AsString () + public override void Emit (EmitContext ec) { - return Value.ToString (); + ec.EmitLong (Value); } public override object GetValue () @@ -1285,12 +1263,18 @@ namespace Mono.CSharp { return Value < 0; } } + + public override bool IsOneInteger { + get { + return Value == 1; + } + } public override bool IsZeroInteger { get { return Value == 0; } } - public override Constant ConvertExplicitly (bool in_checked_context, Type target_type) + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { if (target_type == TypeManager.byte_type) { if (in_checked_context){ @@ -1356,7 +1340,7 @@ namespace Mono.CSharp { return null; } - public override Constant ConvertImplicitly (ResolveContext rc, Type type) + public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec type) { if (Value >= 0 && type == TypeManager.uint64_type) { return new ULongConstant ((ulong) Value, loc).Resolve (rc); @@ -1382,16 +1366,14 @@ namespace Mono.CSharp { return this; } - public override void Emit (EmitContext ec) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) { - ILGenerator ig = ec.ig; - - LongLiteral.EmitLong (ig, unchecked ((long) Value)); + enc.Encode (Value); } - public override string AsString () + public override void Emit (EmitContext ec) { - return Value.ToString (); + ec.EmitLong (unchecked ((long) Value)); } public override object GetValue () @@ -1415,12 +1397,18 @@ namespace Mono.CSharp { return false; } } + + public override bool IsOneInteger { + get { + return Value == 1; + } + } public override bool IsZeroInteger { get { return Value == 0; } } - public override Constant ConvertExplicitly (bool in_checked_context, Type target_type) + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { if (target_type == TypeManager.byte_type) { if (in_checked_context && Value > Byte.MaxValue) @@ -1490,14 +1478,14 @@ namespace Mono.CSharp { return this; } - public override void Emit (EmitContext ec) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) { - ec.ig.Emit (OpCodes.Ldc_R4, Value); + enc.Encode (Value); } - public override string AsString () + public override void Emit (EmitContext ec) { - return Value.ToString (); + ec.Emit (OpCodes.Ldc_R4, Value); } public override object GetValue () @@ -1505,6 +1493,11 @@ namespace Mono.CSharp { return Value; } + public override string GetValueAsLiteral () + { + return Value.ToString (); + } + public override bool IsDefaultValue { get { return Value == 0; @@ -1517,7 +1510,7 @@ namespace Mono.CSharp { } } - public override Constant ConvertExplicitly (bool in_checked_context, Type target_type) + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { if (target_type == TypeManager.byte_type) { if (in_checked_context){ @@ -1608,14 +1601,14 @@ namespace Mono.CSharp { return this; } - public override void Emit (EmitContext ec) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) { - ec.ig.Emit (OpCodes.Ldc_R8, Value); + enc.Encode (Value); } - public override string AsString () + public override void Emit (EmitContext ec) { - return Value.ToString (); + ec.Emit (OpCodes.Ldc_R8, Value); } public override object GetValue () @@ -1623,6 +1616,11 @@ namespace Mono.CSharp { return Value; } + public override string GetValueAsLiteral () + { + return Value.ToString (); + } + public override bool IsDefaultValue { get { return Value == 0; @@ -1635,7 +1633,7 @@ namespace Mono.CSharp { } } - public override Constant ConvertExplicitly (bool in_checked_context, Type target_type) + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { if (target_type == TypeManager.byte_type) { if (in_checked_context){ @@ -1719,11 +1717,6 @@ namespace Mono.CSharp { Value = d; } - override public string AsString () - { - return Value.ToString () + "M"; - } - protected override Expression DoResolve (ResolveContext rc) { type = TypeManager.decimal_type; @@ -1733,13 +1726,16 @@ namespace Mono.CSharp { public override object GetValue () { - return (object) Value; + return Value; } - public override void Emit (EmitContext ec) + public override string GetValueAsLiteral () { - ILGenerator ig = ec.ig; + return Value.ToString () + "M"; + } + public override void Emit (EmitContext ec) + { int [] words = decimal.GetBits (Value); int power = (words [3] >> 16) & 0xff; @@ -1753,8 +1749,8 @@ namespace Mono.CSharp { return; } - IntConstant.EmitInt (ig, (int) Value); - ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg); + ec.EmitInt ((int) Value); + ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg); return; } @@ -1767,21 +1763,21 @@ namespace Mono.CSharp { return; } - LongConstant.EmitLong (ig, (long) Value); - ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_long_arg); + ec.EmitLong ((long) Value); + ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_long_arg); return; } } - IntConstant.EmitInt (ig, words [0]); - IntConstant.EmitInt (ig, words [1]); - IntConstant.EmitInt (ig, words [2]); + ec.EmitInt (words [0]); + ec.EmitInt (words [1]); + ec.EmitInt (words [2]); // sign - IntConstant.EmitInt (ig, words [3] >> 31); + ec.EmitInt (words [3] >> 31); // power - IntConstant.EmitInt (ig, power); + ec.EmitInt (power); if (TypeManager.void_decimal_ctor_five_args == null) { TypeManager.void_decimal_ctor_five_args = TypeManager.GetPredefinedConstructor ( @@ -1792,7 +1788,7 @@ namespace Mono.CSharp { return; } - ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args); + ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args); } public override bool IsDefaultValue { @@ -1807,7 +1803,7 @@ namespace Mono.CSharp { } } - public override Constant ConvertExplicitly (bool in_checked_context, Type target_type) + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { if (target_type == TypeManager.sbyte_type) return new SByteConstant ((sbyte)Value, loc); @@ -1846,12 +1842,6 @@ namespace Mono.CSharp { Value = s; } - // FIXME: Escape the string. - override public string AsString () - { - return "\"" + Value + "\""; - } - protected override Expression DoResolve (ResolveContext rc) { type = TypeManager.string_type; @@ -1863,11 +1853,17 @@ namespace Mono.CSharp { { return Value; } + + public override string GetValueAsLiteral () + { + // FIXME: Escape the string. + return "\"" + Value + "\""; + } public override void Emit (EmitContext ec) { if (Value == null) { - ec.ig.Emit (OpCodes.Ldnull); + ec.Emit (OpCodes.Ldnull); return; } @@ -1875,17 +1871,26 @@ namespace Mono.CSharp { // Use string.Empty for both literals and constants even if // it's not allowed at language level // - if (Value.Length == 0 && RootContext.Optimize && !TypeManager.IsEqual (ec.CurrentType, TypeManager.string_type)) { + if (Value.Length == 0 && RootContext.Optimize && ec.CurrentType != TypeManager.string_type) { if (TypeManager.string_empty == null) - TypeManager.string_empty = TypeManager.GetPredefinedField (TypeManager.string_type, "Empty", loc); + TypeManager.string_empty = TypeManager.GetPredefinedField (TypeManager.string_type, "Empty", loc, TypeManager.string_type); if (TypeManager.string_empty != null) { - ec.ig.Emit (OpCodes.Ldsfld, TypeManager.string_empty); + ec.Emit (OpCodes.Ldsfld, TypeManager.string_empty); return; } } - ec.ig.Emit (OpCodes.Ldstr, Value); + ec.Emit (OpCodes.Ldstr, Value); + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + // cast to object + if (type != targetType) + enc.Encode (type); + + enc.Encode (Value); } public override bool IsDefaultValue { @@ -1906,7 +1911,7 @@ namespace Mono.CSharp { } } - public override Constant ConvertExplicitly (bool in_checked_context, Type target_type) + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { return null; } @@ -1917,16 +1922,23 @@ namespace Mono.CSharp { // public class NullConstant : Constant { - public NullConstant (Type type, Location loc) + public NullConstant (TypeSpec type, Location loc) : base (loc) { eclass = ExprClass.Value; this.type = type; } - public override string AsString () + public override Expression CreateExpressionTree (ResolveContext ec) { - return GetSignatureForError (); + if (type == InternalType.Null || type == TypeManager.object_type) { + // Optimized version, also avoids referencing literal internal type + Arguments args = new Arguments (1); + args.Add (new Argument (this)); + return CreateExpressionFactoryCall (ec, "Constant", args); + } + + return base.CreateExpressionTree (ec); } protected override Expression DoResolve (ResolveContext ec) @@ -1934,13 +1946,30 @@ namespace Mono.CSharp { return this; } + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + // Type it as string cast + if (targetType == TypeManager.object_type || targetType == InternalType.Null) + enc.Encode (TypeManager.string_type); + + var ac = targetType as ArrayContainer; + if (ac != null) { + if (ac.Rank != 1 || ac.Element.IsArray) + base.EncodeAttributeValue (rc, enc, targetType); + else + enc.Encode (uint.MaxValue); + } else { + enc.Encode (byte.MaxValue); + } + } + public override void Emit (EmitContext ec) { - ec.ig.Emit (OpCodes.Ldnull); + ec.Emit (OpCodes.Ldnull); // Only to make verifier happy if (TypeManager.IsGenericParameter (type)) - ec.ig.Emit (OpCodes.Unbox_Any, type); + ec.Emit (OpCodes.Unbox_Any, type); } public override string ExprClassName { @@ -1949,12 +1978,7 @@ namespace Mono.CSharp { } } - public override string GetSignatureForError () - { - return "null"; - } - - public override Constant ConvertExplicitly (bool inCheckedContext, Type targetType) + public override Constant ConvertExplicitly (bool inCheckedContext, TypeSpec targetType) { if (targetType.IsPointer) { if (IsLiteral || this is NullPointer) @@ -1964,7 +1988,7 @@ namespace Mono.CSharp { } // Exlude internal compiler types - if (targetType == InternalType.AnonymousMethod) + if (targetType.Kind == MemberKind.InternalCompilerType && targetType != InternalType.Dynamic && targetType != InternalType.Null) return null; if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType)) @@ -1979,16 +2003,26 @@ namespace Mono.CSharp { return null; } - public override Constant ConvertImplicitly (ResolveContext rc, Type targetType) + public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec targetType) { return ConvertExplicitly (false, targetType); } + public override string GetSignatureForError () + { + return "null"; + } + public override object GetValue () { return null; } + public override string GetValueAsLiteral () + { + return GetSignatureForError (); + } + public override bool IsDefaultValue { get { return true; } } @@ -2004,11 +2038,6 @@ namespace Mono.CSharp { public override bool IsZeroInteger { get { return true; } } - - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - type = storey.MutateType (type); - } } /// @@ -2028,11 +2057,6 @@ namespace Mono.CSharp { this.side_effect = side_effect; } - public override string AsString () - { - return value.AsString (); - } - protected override Expression DoResolve (ResolveContext rc) { value = value.Resolve (rc); @@ -2047,6 +2071,11 @@ namespace Mono.CSharp { return value.GetValue (); } + public override string GetValueAsLiteral () + { + return value.GetValueAsLiteral (); + } + public override void Emit (EmitContext ec) { side_effect.EmitSideEffect (ec); @@ -2071,7 +2100,7 @@ namespace Mono.CSharp { get { return value.IsZeroInteger; } } - public override Constant ConvertExplicitly (bool in_checked_context, Type target_type) + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { Constant new_value = value.ConvertExplicitly (in_checked_context, target_type); return new_value == null ? null : new SideEffectConstant (new_value, side_effect, new_value.Location);