X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fconstant.cs;h=d16e844d5920ddbed58d104da25055d308b45be7;hb=faf1e90312a15b30f99686aa41f05ab891cf6027;hp=d9f1b58e8df940af1ce6cd2ada0e1666d32078f8;hpb=cf83c7d74e8c11184e76ad7dcb2476c274a7ddd5;p=mono.git diff --git a/mcs/mcs/constant.cs b/mcs/mcs/constant.cs index d9f1b58e8df..d16e844d592 100644 --- a/mcs/mcs/constant.cs +++ b/mcs/mcs/constant.cs @@ -9,52 +9,32 @@ // Copyright 2003-2008 Novell, Inc. // -namespace Mono.CSharp { +using System; +using System.Globalization; + +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif - using System; - using System.Reflection.Emit; - using System.Collections; +namespace Mono.CSharp { /// /// Base class for constants and literals. /// - public abstract class Constant : Expression { + public abstract class Constant : Expression + { + static readonly NumberFormatInfo nfi = CultureInfo.InvariantCulture.NumberFormat; protected Constant (Location loc) { 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 (Type value_type, out object value) - { - if (value_type == TypeManager.object_type) { - value = GetTypedValue (); - return true; - } - - Constant c = ImplicitConversionRequired (value_type, loc); - if (c == null) { - value = null; - return false; - } - - value = c.GetTypedValue (); - return true; + return this.GetType ().Name + " (" + GetValueAsLiteral () + ")"; } /// @@ -63,38 +43,42 @@ namespace Mono.CSharp { /// public abstract object GetValue (); + public abstract long GetValueAsLong (); + + public abstract string GetValueAsLiteral (); + +#if !STATIC + // + // Returns an object value which is typed to contant type + // public virtual object GetTypedValue () { return GetValue (); } +#endif - /// - /// Constants are always born in a fully resolved state - /// - public override Expression DoResolve (EmitContext ec) - { - return this; - } - - public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl) + public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) { - if (!expl && IsLiteral && type != TypeManager.string_type && !TypeManager.IsDelegateType (target)) { - Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'", - GetValue ().ToString (), TypeManager.CSharpName (target)); + if (!expl && IsLiteral && + BuildinTypeSpec.IsPrimitiveTypeOrDecimal (target) && + BuildinTypeSpec.IsPrimitiveTypeOrDecimal (type)) { + ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'", + GetValueAsLiteral (), TypeManager.CSharpName (target)); } else { base.Error_ValueCannotBeConverted (ec, loc, target, expl); } } - public Constant ImplicitConversionRequired (Type type, Location loc) + public Constant ImplicitConversionRequired (ResolveContext ec, TypeSpec type, Location loc) { Constant c = ConvertImplicitly (type); if (c == null) - Error_ValueCannotBeConverted (null, loc, type, false); + Error_ValueCannotBeConverted (ec, loc, type, false); + return c; } - public virtual Constant ConvertImplicitly (Type type) + public virtual Constant ConvertImplicitly (TypeSpec type) { if (this.type == type) return this; @@ -103,7 +87,7 @@ namespace Mono.CSharp { return null; bool fail; - object constant_value = TypeManager.ChangeType (GetValue (), type, out fail); + object constant_value = ChangeType (GetValue (), type, out fail); if (fail){ // // We should always catch the error before this is ever @@ -116,89 +100,177 @@ namespace Mono.CSharp { return CreateConstant (type, constant_value, loc); } - /// Returns a constant instance based on Type - /// The returned value is already resolved. - public static Constant CreateConstant (Type t, object v, Location loc) - { - if (t == TypeManager.int32_type) - return new IntConstant ((int) v, loc); - if (t == TypeManager.string_type) - return new StringConstant ((string) v, loc); - if (t == TypeManager.uint32_type) - return new UIntConstant ((uint) v, loc); - if (t == TypeManager.int64_type) - return new LongConstant ((long) v, loc); - if (t == TypeManager.uint64_type) - return new ULongConstant ((ulong) v, loc); - if (t == TypeManager.float_type) - return new FloatConstant ((float) v, loc); - if (t == TypeManager.double_type) - return new DoubleConstant ((double) v, loc); - if (t == TypeManager.short_type) - return new ShortConstant ((short)v, loc); - if (t == TypeManager.ushort_type) - return new UShortConstant ((ushort)v, loc); - if (t == TypeManager.sbyte_type) - return new SByteConstant ((sbyte)v, loc); - if (t == TypeManager.byte_type) - return new ByteConstant ((byte)v, loc); - if (t == TypeManager.char_type) - return new CharConstant ((char)v, loc); - if (t == TypeManager.bool_type) - return new BoolConstant ((bool) v, loc); - if (t == TypeManager.decimal_type) - return new DecimalConstant ((decimal) v, loc); - if (TypeManager.IsEnumType (t)) { - Type real_type = TypeManager.GetEnumUnderlyingType (t); - return new EnumConstant (CreateConstant (real_type, v, loc), t); - } - if (v == null && !TypeManager.IsValueType (t)) - return new EmptyConstantCast (new NullLiteral (loc), t); - - throw new Exception ("Unknown type for constant (" + t + - "), details: " + v); - } - - public override Expression CreateExpressionTree (EmitContext ec) - { - ArrayList args = new ArrayList (2); - args.Add (new Argument (this)); - args.Add (new Argument ( - new TypeOf (new TypeExpression (type, loc), loc))); + // + // Returns a constant instance based on Type + // + public static Constant CreateConstant (TypeSpec t, object v, Location loc) + { + return CreateConstantFromValue (t, v, loc); + } + + public static Constant CreateConstantFromValue (TypeSpec t, object v, Location loc) + { + switch (t.BuildinType) { + case BuildinTypeSpec.Type.Int: + return new IntConstant (t, (int) v, loc); + case BuildinTypeSpec.Type.String: + return new StringConstant (t, (string) v, loc); + case BuildinTypeSpec.Type.UInt: + return new UIntConstant (t, (uint) v, loc); + case BuildinTypeSpec.Type.Long: + return new LongConstant (t, (long) v, loc); + case BuildinTypeSpec.Type.ULong: + return new ULongConstant (t, (ulong) v, loc); + case BuildinTypeSpec.Type.Float: + return new FloatConstant (t, (float) v, loc); + case BuildinTypeSpec.Type.Double: + return new DoubleConstant (t, (double) v, loc); + case BuildinTypeSpec.Type.Short: + return new ShortConstant (t, (short) v, loc); + case BuildinTypeSpec.Type.UShort: + return new UShortConstant (t, (ushort) v, loc); + case BuildinTypeSpec.Type.SByte: + return new SByteConstant (t, (sbyte) v, loc); + case BuildinTypeSpec.Type.Byte: + return new ByteConstant (t, (byte) v, loc); + case BuildinTypeSpec.Type.Char: + return new CharConstant (t, (char) v, loc); + case BuildinTypeSpec.Type.Bool: + return new BoolConstant (t, (bool) v, loc); + case BuildinTypeSpec.Type.Decimal: + return new DecimalConstant (t, (decimal) v, loc); + } + + if (t.IsEnum) { + var real_type = EnumSpec.GetUnderlyingType (t); + return new EnumConstant (CreateConstantFromValue (real_type, v, loc), t); + } + + if (v == null) { + if (t.IsNullableType) + return Nullable.LiftedNull.Create (t, loc); - return CreateExpressionFactoryCall ("Constant", args); + if (TypeManager.IsReferenceType (t)) + return new NullConstant (t, loc); + } + + throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'", + v, TypeManager.CSharpName (t)); } + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (2); + args.Add (new Argument (this)); + args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc))); + + return CreateExpressionFactoryCall (ec, "Constant", args); + } /// /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type. /// 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); + + // This is a custom version of Convert.ChangeType() which works + // with the TypeBuilder defined types when compiling corlib. + static object ChangeType (object value, TypeSpec targetType, out bool error) + { + IConvertible convert_value = value as IConvertible; + + if (convert_value == null) { + error = true; + return null; + } + + // + // We cannot rely on build-in type conversions as they are + // more limited than what C# supports. + // See char -> float/decimal/double conversion + // + error = false; + try { + switch (targetType.BuildinType) { + case BuildinTypeSpec.Type.Bool: + return convert_value.ToBoolean (nfi); + case BuildinTypeSpec.Type.Byte: + return convert_value.ToByte (nfi); + case BuildinTypeSpec.Type.Char: + return convert_value.ToChar (nfi); + case BuildinTypeSpec.Type.Short: + return convert_value.ToInt16 (nfi); + case BuildinTypeSpec.Type.Int: + return convert_value.ToInt32 (nfi); + case BuildinTypeSpec.Type.Long: + return convert_value.ToInt64 (nfi); + case BuildinTypeSpec.Type.SByte: + return convert_value.ToSByte (nfi); + case BuildinTypeSpec.Type.Decimal: + if (convert_value.GetType () == typeof (char)) + return (decimal) convert_value.ToInt32 (nfi); + return convert_value.ToDecimal (nfi); + case BuildinTypeSpec.Type.Double: + if (convert_value.GetType () == typeof (char)) + return (double) convert_value.ToInt32 (nfi); + return convert_value.ToDouble (nfi); + case BuildinTypeSpec.Type.Float: + if (convert_value.GetType () == typeof (char)) + return (float) convert_value.ToInt32 (nfi); + return convert_value.ToSingle (nfi); + case BuildinTypeSpec.Type.String: + return convert_value.ToString (nfi); + case BuildinTypeSpec.Type.UShort: + return convert_value.ToUInt16 (nfi); + case BuildinTypeSpec.Type.UInt: + return convert_value.ToUInt32 (nfi); + case BuildinTypeSpec.Type.ULong: + return convert_value.ToUInt64 (nfi); + case BuildinTypeSpec.Type.Object: + return value; + } + } catch { + } + + error = true; + return null; + } + + protected override Expression DoResolve (ResolveContext rc) + { + return this; + } /// /// Attempts to do a compile-time folding of a constant cast. /// - public Constant TryReduce (EmitContext ec, Type target_type, Location loc) + public Constant TryReduce (ResolveContext ec, TypeSpec target_type, Location loc) { try { return TryReduce (ec, target_type); } catch (OverflowException) { - Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)", - GetValue ().ToString (), TypeManager.CSharpName (target_type)); - return null; + 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, loc); } } - Constant TryReduce (EmitContext ec, Type target_type) + Constant TryReduce (ResolveContext ec, TypeSpec target_type) { if (Type == target_type) return this; + Constant c; if (TypeManager.IsEnumType (target_type)) { - Constant c = TryReduce (ec, TypeManager.GetEnumUnderlyingType (target_type)); + c = TryReduce (ec, EnumSpec.GetUnderlyingType (target_type)); if (c == null) return null; @@ -208,18 +280,16 @@ namespace Mono.CSharp { return ConvertExplicitly (ec.ConstantCheckState, target_type); } - public abstract Constant Increment (); - /// /// 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; - return Type == TypeManager.null_type; + return this is NullLiteral; } public abstract bool IsDefaultValue { @@ -236,6 +306,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, @@ -250,19 +324,43 @@ namespace Mono.CSharp { // do nothing } + public sealed override Expression Clone (CloneContext clonectx) + { + // No cloning is not needed for constants + return this; + } + protected override void CloneTo (CloneContext clonectx, Expression target) { - // CloneTo: Nothing, we do not keep any state on this expression + throw new NotSupportedException ("should not be reached"); + } + + public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + return System.Linq.Expressions.Expression.Constant (GetTypedValue (), type.GetMetaInfo ()); +#endif + } + + public new bool Resolve (ResolveContext rc) + { + // It exists only as hint not to call Resolve on constants + return true; } } - public abstract class IntegralConstant : Constant { - protected IntegralConstant (Location loc) : - base (loc) + public abstract class IntegralConstant : Constant + { + protected IntegralConstant (TypeSpec type, Location loc) + : base (loc) { + this.type = type; + eclass = ExprClass.Value; } - public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl) + public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) { try { ConvertExplicitly (true, target); @@ -270,48 +368,64 @@ namespace Mono.CSharp { } catch { - Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'", + ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'", GetValue ().ToString (), TypeManager.CSharpName (target)); } } + + public override string GetValueAsLiteral () + { + return GetValue ().ToString (); + } + + public abstract Constant Increment (); } public class BoolConstant : Constant { public readonly bool Value; + + public BoolConstant (BuildinTypes types, bool val, Location loc) + : this (types.Bool, val, loc) + { + } - public BoolConstant (bool val, Location loc): - base (loc) + public BoolConstant (TypeSpec type, bool val, Location loc) + : base (loc) { - type = TypeManager.bool_type; eclass = ExprClass.Value; + this.type = type; Value = val; } - override public string AsString () + public override object GetValue () + { + return (object) Value; + } + + public override string GetValueAsLiteral () { return Value ? "true" : "false"; } - public override object GetValue () + public override long GetValueAsLong () { - return (object) Value; + return Value ? 1 : 0; + } + + 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 Constant Increment () - { - throw new NotSupportedException (); - } - public override bool IsDefaultValue { get { return !Value; @@ -328,32 +442,36 @@ 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; } } - public class ByteConstant : IntegralConstant { + public class ByteConstant : IntegralConstant + { public readonly byte Value; - public ByteConstant (byte v, Location loc): - base (loc) + public ByteConstant (BuildinTypes types, byte v, Location loc) + : this (types.Byte, v, loc) + { + } + + public ByteConstant (TypeSpec type, byte v, Location loc) + : base (type, loc) { - type = TypeManager.byte_type; - eclass = ExprClass.Value; 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); } public override object GetValue () @@ -361,9 +479,14 @@ namespace Mono.CSharp { return Value; } + public override long GetValueAsLong () + { + return Value; + } + public override Constant Increment () { - return new ByteConstant (checked ((byte)(Value + 1)), loc); + return new ByteConstant (type, checked ((byte)(Value + 1)), loc); } public override bool IsDefaultValue { @@ -372,6 +495,12 @@ namespace Mono.CSharp { } } + public override bool IsOneInteger { + get { + return Value == 1; + } + } + public override bool IsNegative { get { return false; @@ -382,35 +511,36 @@ 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) { + switch (target_type.BuildinType) { + case BuildinTypeSpec.Type.SByte: if (in_checked_context){ if (Value > SByte.MaxValue) throw new OverflowException (); } - return new SByteConstant ((sbyte) Value, Location); - } - if (target_type == TypeManager.short_type) - return new ShortConstant ((short) Value, Location); - if (target_type == TypeManager.ushort_type) - return new UShortConstant ((ushort) Value, Location); - if (target_type == TypeManager.int32_type) - return new IntConstant ((int) Value, Location); - if (target_type == TypeManager.uint32_type) - return new UIntConstant ((uint) Value, Location); - if (target_type == TypeManager.int64_type) - return new LongConstant ((long) Value, Location); - if (target_type == TypeManager.uint64_type) - return new ULongConstant ((ulong) Value, Location); - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) Value, Location); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) Value, Location); - if (target_type == TypeManager.char_type) - return new CharConstant ((char) Value, Location); - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) Value, Location); + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuildinTypeSpec.Type.Short: + return new ShortConstant (target_type, (short) Value, Location); + case BuildinTypeSpec.Type.UShort: + return new UShortConstant (target_type, (ushort) Value, Location); + case BuildinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, Location); + case BuildinTypeSpec.Type.UInt: + return new UIntConstant (target_type, (uint) Value, Location); + case BuildinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuildinTypeSpec.Type.ULong: + return new ULongConstant (target_type, (ulong) Value, Location); + case BuildinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuildinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuildinTypeSpec.Type.Char: + return new CharConstant (target_type, (char) Value, Location); + case BuildinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } return null; } @@ -420,20 +550,31 @@ namespace Mono.CSharp { public class CharConstant : Constant { public readonly char Value; - public CharConstant (char v, Location loc): - base (loc) + public CharConstant (BuildinTypes types, char v, Location loc) + : this (types.Char, v, loc) + { + } + + public CharConstant (TypeSpec type, char v, Location loc) + : base (loc) { - type = TypeManager.char_type; + this.type = type; eclass = ExprClass.Value; + Value = v; } + 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 public string descape (char c) + static string descape (char c) { switch (c){ case '\a': @@ -462,21 +603,21 @@ 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 long GetValueAsLong () { return Value; } - public override Constant Increment () + public override string GetValueAsLiteral () { - return new CharConstant (checked ((char)(Value + 1)), loc); + return "\"" + descape (Value) + "\""; } - + public override bool IsDefaultValue { get { return Value == 0; @@ -493,68 +634,72 @@ 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){ + switch (target_type.BuildinType) { + case BuildinTypeSpec.Type.Byte: + if (in_checked_context) { if (Value < Byte.MinValue || Value > Byte.MaxValue) throw new OverflowException (); } - return new ByteConstant ((byte) Value, Location); - } - if (target_type == TypeManager.sbyte_type) { - if (in_checked_context){ + return new ByteConstant (target_type, (byte) Value, Location); + case BuildinTypeSpec.Type.SByte: + if (in_checked_context) { if (Value > SByte.MaxValue) throw new OverflowException (); } - return new SByteConstant ((sbyte) Value, Location); - } - if (target_type == TypeManager.short_type) { - if (in_checked_context){ + return new SByteConstant (target_type, (sbyte) Value, Location); + + case BuildinTypeSpec.Type.Short: + if (in_checked_context) { if (Value > Int16.MaxValue) throw new OverflowException (); - } - return new ShortConstant ((short) Value, Location); - } - if (target_type == TypeManager.int32_type) - return new IntConstant ((int) Value, Location); - if (target_type == TypeManager.uint32_type) - return new UIntConstant ((uint) Value, Location); - if (target_type == TypeManager.int64_type) - return new LongConstant ((long) Value, Location); - if (target_type == TypeManager.uint64_type) - return new ULongConstant ((ulong) Value, Location); - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) Value, Location); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) Value, Location); - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) Value, Location); + } + return new ShortConstant (target_type, (short) Value, Location); + case BuildinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, Location); + case BuildinTypeSpec.Type.UInt: + return new UIntConstant (target_type, (uint) Value, Location); + case BuildinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuildinTypeSpec.Type.ULong: + return new ULongConstant (target_type, (ulong) Value, Location); + case BuildinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuildinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuildinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } return null; } } - public class SByteConstant : IntegralConstant { + public class SByteConstant : IntegralConstant + { public readonly sbyte Value; - public SByteConstant (sbyte v, Location loc): - base (loc) + public SByteConstant (BuildinTypes types, sbyte v, Location loc) + : this (types.SByte, v, loc) + { + } + + public SByteConstant (TypeSpec type, sbyte v, Location loc) + : base (type, loc) { - type = TypeManager.sbyte_type; - eclass = ExprClass.Value; 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); } public override object GetValue () @@ -562,9 +707,14 @@ namespace Mono.CSharp { return Value; } + public override long GetValueAsLong () + { + return Value; + } + public override Constant Increment () { - return new SByteConstant (checked((sbyte)(Value + 1)), loc); + return new SByteConstant (type, checked((sbyte)(Value + 1)), loc); } public override bool IsDefaultValue { @@ -579,47 +729,52 @@ 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) { + switch (target_type.BuildinType) { + case BuildinTypeSpec.Type.Byte: if (in_checked_context && Value < 0) throw new OverflowException (); - return new ByteConstant ((byte) Value, Location); - } - if (target_type == TypeManager.short_type) - return new ShortConstant ((short) Value, Location); - if (target_type == TypeManager.ushort_type) { + return new ByteConstant (target_type, (byte) Value, Location); + case BuildinTypeSpec.Type.Short: + return new ShortConstant (target_type, (short) Value, Location); + case BuildinTypeSpec.Type.UShort: if (in_checked_context && Value < 0) throw new OverflowException (); - return new UShortConstant ((ushort) Value, Location); - } if (target_type == TypeManager.int32_type) - return new IntConstant ((int) Value, Location); - if (target_type == TypeManager.uint32_type) { + return new UShortConstant (target_type, (ushort) Value, Location); + case BuildinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, Location); + case BuildinTypeSpec.Type.UInt: if (in_checked_context && Value < 0) throw new OverflowException (); - return new UIntConstant ((uint) Value, Location); - } if (target_type == TypeManager.int64_type) - return new LongConstant ((long) Value, Location); - if (target_type == TypeManager.uint64_type) { + return new UIntConstant (target_type, (uint) Value, Location); + case BuildinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuildinTypeSpec.Type.ULong: if (in_checked_context && Value < 0) throw new OverflowException (); - return new ULongConstant ((ulong) Value, Location); - } - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) Value, Location); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) Value, Location); - if (target_type == TypeManager.char_type) { + return new ULongConstant (target_type, (ulong) Value, Location); + case BuildinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuildinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuildinTypeSpec.Type.Char: if (in_checked_context && Value < 0) throw new OverflowException (); - return new CharConstant ((char) Value, Location); + return new CharConstant (target_type, (char) Value, Location); + case BuildinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) Value, Location); return null; } @@ -629,22 +784,25 @@ namespace Mono.CSharp { public class ShortConstant : IntegralConstant { public readonly short Value; - public ShortConstant (short v, Location loc): - base (loc) + public ShortConstant (BuildinTypes types, short v, Location loc) + : this (types.Short, v, loc) + { + } + + public ShortConstant (TypeSpec type, short v, Location loc) + : base (type, loc) { - type = TypeManager.short_type; - eclass = ExprClass.Value; 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); } public override object GetValue () @@ -652,9 +810,14 @@ namespace Mono.CSharp { return Value; } + public override long GetValueAsLong () + { + return Value; + } + public override Constant Increment () { - return new ShortConstant (checked((short)(Value + 1)), loc); + return new ShortConstant (type, checked((short)(Value + 1)), loc); } public override bool IsDefaultValue { @@ -672,91 +835,102 @@ 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){ + switch (target_type.BuildinType) { + case BuildinTypeSpec.Type.Byte: + if (in_checked_context) { if (Value < Byte.MinValue || Value > Byte.MaxValue) throw new OverflowException (); } - return new ByteConstant ((byte) Value, Location); - } - if (target_type == TypeManager.sbyte_type) { - if (in_checked_context){ + return new ByteConstant (target_type, (byte) Value, Location); + case BuildinTypeSpec.Type.SByte: + if (in_checked_context) { if (Value < SByte.MinValue || Value > SByte.MaxValue) throw new OverflowException (); } - return new SByteConstant ((sbyte) Value, Location); - } - if (target_type == TypeManager.ushort_type) { + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuildinTypeSpec.Type.UShort: if (in_checked_context && Value < 0) throw new OverflowException (); - - return new UShortConstant ((ushort) Value, Location); - } - if (target_type == TypeManager.int32_type) - return new IntConstant ((int) Value, Location); - if (target_type == TypeManager.uint32_type) { + + return new UShortConstant (target_type, (ushort) Value, Location); + case BuildinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, Location); + case BuildinTypeSpec.Type.UInt: if (in_checked_context && Value < 0) throw new OverflowException (); - return new UIntConstant ((uint) Value, Location); - } - if (target_type == TypeManager.int64_type) - return new LongConstant ((long) Value, Location); - if (target_type == TypeManager.uint64_type) { + return new UIntConstant (target_type, (uint) Value, Location); + case BuildinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuildinTypeSpec.Type.ULong: if (in_checked_context && Value < 0) throw new OverflowException (); - return new ULongConstant ((ulong) Value, Location); - } - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) Value, Location); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) Value, Location); - if (target_type == TypeManager.char_type) { - if (in_checked_context){ + return new ULongConstant (target_type, (ulong) Value, Location); + case BuildinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuildinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuildinTypeSpec.Type.Char: + if (in_checked_context) { if (Value < Char.MinValue) throw new OverflowException (); } - return new CharConstant ((char) Value, Location); + return new CharConstant (target_type, (char) Value, Location); + case BuildinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) Value, Location); return null; } } - public class UShortConstant : IntegralConstant { + public class UShortConstant : IntegralConstant + { public readonly ushort Value; - public UShortConstant (ushort v, Location loc): - base (loc) + public UShortConstant (BuildinTypes types, ushort v, Location loc) + : this (types.UShort, v, loc) + { + } + + public UShortConstant (TypeSpec type, ushort v, Location loc) + : base (type, loc) { - type = TypeManager.ushort_type; - eclass = ExprClass.Value; 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); } public override object GetValue () { return Value; } + + public override long GetValueAsLong () + { + return Value; + } public override Constant Increment () { - return new UShortConstant (checked((ushort)(Value + 1)), loc); + return new UShortConstant (type, checked((ushort)(Value + 1)), loc); } public override bool IsDefaultValue { @@ -770,141 +944,102 @@ 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){ + switch (target_type.BuildinType) { + case BuildinTypeSpec.Type.Byte: + if (in_checked_context) { if (Value > Byte.MaxValue) throw new OverflowException (); } - return new ByteConstant ((byte) Value, Location); - } - if (target_type == TypeManager.sbyte_type) { - if (in_checked_context){ + return new ByteConstant (target_type, (byte) Value, Location); + case BuildinTypeSpec.Type.SByte: + if (in_checked_context) { if (Value > SByte.MaxValue) throw new OverflowException (); } - return new SByteConstant ((sbyte) Value, Location); - } - if (target_type == TypeManager.short_type) { - if (in_checked_context){ + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuildinTypeSpec.Type.Short: + if (in_checked_context) { if (Value > Int16.MaxValue) throw new OverflowException (); } - return new ShortConstant ((short) Value, Location); - } - if (target_type == TypeManager.int32_type) - return new IntConstant ((int) Value, Location); - if (target_type == TypeManager.uint32_type) - return new UIntConstant ((uint) Value, Location); - if (target_type == TypeManager.int64_type) - return new LongConstant ((long) Value, Location); - if (target_type == TypeManager.uint64_type) - return new ULongConstant ((ulong) Value, Location); - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) Value, Location); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) Value, Location); - if (target_type == TypeManager.char_type) { - if (in_checked_context){ + return new ShortConstant (target_type, (short) Value, Location); + case BuildinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, Location); + case BuildinTypeSpec.Type.UInt: + return new UIntConstant (target_type, (uint) Value, Location); + case BuildinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuildinTypeSpec.Type.ULong: + return new ULongConstant (target_type, (ulong) Value, Location); + case BuildinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuildinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuildinTypeSpec.Type.Char: + if (in_checked_context) { if (Value > Char.MaxValue) throw new OverflowException (); } - return new CharConstant ((char) Value, Location); + return new CharConstant (target_type, (char) Value, Location); + case BuildinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) Value, Location); return null; } } - public class IntConstant : IntegralConstant { + public class IntConstant : IntegralConstant + { public readonly int Value; - public IntConstant (int v, Location loc): - base (loc) + public IntConstant (BuildinTypes types, int v, Location loc) + : this (types.Int, v, loc) { - type = TypeManager.int32_type; - eclass = ExprClass.Value; - Value = v; } - static public void EmitInt (ILGenerator ig, int i) + public IntConstant (TypeSpec type, int v, Location loc) + : base (type, loc) { - 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; + Value = v; + } - 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 EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); } public override void Emit (EmitContext ec) { - EmitInt (ec.ig, Value); + ec.EmitInt (Value); } - public override string AsString () + public override object GetValue () { - return Value.ToString (); + return Value; } - public override object GetValue () + public override long GetValueAsLong () { return Value; } public override Constant Increment () { - return new IntConstant (checked(Value + 1), loc); + return new IntConstant (type, checked(Value + 1), loc); } public override bool IsDefaultValue { @@ -918,80 +1053,81 @@ 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){ + switch (target_type.BuildinType) { + case BuildinTypeSpec.Type.Byte: + if (in_checked_context) { if (Value < Byte.MinValue || Value > Byte.MaxValue) throw new OverflowException (); } - return new ByteConstant ((byte) Value, Location); - } - if (target_type == TypeManager.sbyte_type) { - if (in_checked_context){ + return new ByteConstant (target_type, (byte) Value, Location); + case BuildinTypeSpec.Type.SByte: + if (in_checked_context) { if (Value < SByte.MinValue || Value > SByte.MaxValue) throw new OverflowException (); } - return new SByteConstant ((sbyte) Value, Location); - } - if (target_type == TypeManager.short_type) { - if (in_checked_context){ + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuildinTypeSpec.Type.Short: + if (in_checked_context) { if (Value < Int16.MinValue || Value > Int16.MaxValue) throw new OverflowException (); } - return new ShortConstant ((short) Value, Location); - } - if (target_type == TypeManager.ushort_type) { - if (in_checked_context){ + return new ShortConstant (target_type, (short) Value, Location); + case BuildinTypeSpec.Type.UShort: + if (in_checked_context) { if (Value < UInt16.MinValue || Value > UInt16.MaxValue) throw new OverflowException (); } - return new UShortConstant ((ushort) Value, Location); - } - if (target_type == TypeManager.uint32_type) { - if (in_checked_context){ + return new UShortConstant (target_type, (ushort) Value, Location); + case BuildinTypeSpec.Type.UInt: + if (in_checked_context) { if (Value < UInt32.MinValue) throw new OverflowException (); } - return new UIntConstant ((uint) Value, Location); - } - if (target_type == TypeManager.int64_type) - return new LongConstant ((long) Value, Location); - if (target_type == TypeManager.uint64_type) { + return new UIntConstant (target_type, (uint) Value, Location); + case BuildinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuildinTypeSpec.Type.ULong: if (in_checked_context && Value < 0) throw new OverflowException (); - return new ULongConstant ((ulong) Value, Location); - } - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) Value, Location); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) Value, Location); - if (target_type == TypeManager.char_type) { - if (in_checked_context){ + return new ULongConstant (target_type, (ulong) Value, Location); + case BuildinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuildinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuildinTypeSpec.Type.Char: + if (in_checked_context) { if (Value < Char.MinValue || Value > Char.MaxValue) throw new OverflowException (); } - return new CharConstant ((char) Value, Location); + return new CharConstant (target_type, (char) Value, Location); + case BuildinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) Value, Location); return null; } - public override Constant ConvertImplicitly (Type type) + public override Constant ConvertImplicitly (TypeSpec type) { if (this.type == type) return this; Constant c = TryImplicitIntConversion (type); if (c != null) - return c; + return c; //.Resolve (rc); return base.ConvertImplicitly (type); } @@ -1001,41 +1137,43 @@ 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) { + switch (target_type.BuildinType) { + case BuildinTypeSpec.Type.SByte: if (Value >= SByte.MinValue && Value <= SByte.MaxValue) - return new SByteConstant ((sbyte) Value, loc); - } - else if (target_type == TypeManager.byte_type) { + return new SByteConstant (target_type, (sbyte) Value, loc); + break; + case BuildinTypeSpec.Type.Byte: if (Value >= Byte.MinValue && Value <= Byte.MaxValue) - return new ByteConstant ((byte) Value, loc); - } - else if (target_type == TypeManager.short_type) { + return new ByteConstant (target_type, (byte) Value, loc); + break; + case BuildinTypeSpec.Type.Short: if (Value >= Int16.MinValue && Value <= Int16.MaxValue) - return new ShortConstant ((short) Value, loc); - } - else if (target_type == TypeManager.ushort_type) { + return new ShortConstant (target_type, (short) Value, loc); + break; + case BuildinTypeSpec.Type.UShort: if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue) - return new UShortConstant ((ushort) Value, loc); - } - else if (target_type == TypeManager.uint32_type) { + return new UShortConstant (target_type, (ushort) Value, loc); + break; + case BuildinTypeSpec.Type.UInt: if (Value >= 0) - return new UIntConstant ((uint) Value, loc); - } - else if (target_type == TypeManager.uint64_type) { + return new UIntConstant (target_type, (uint) Value, loc); + break; + case BuildinTypeSpec.Type.ULong: // // we can optimize this case: a positive int32 // always fits on a uint64. But we need an opcode // to do it. // if (Value >= 0) - return new ULongConstant ((ulong) Value, loc); - } - else if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) Value, loc); - else if (target_type == TypeManager.float_type) - return new FloatConstant ((float) Value, loc); + return new ULongConstant (target_type, (ulong) Value, loc); + break; + case BuildinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, loc); + case BuildinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, loc); + } return null; } @@ -1044,22 +1182,25 @@ namespace Mono.CSharp { public class UIntConstant : IntegralConstant { public readonly uint Value; - public UIntConstant (uint v, Location loc): - base (loc) + public UIntConstant (BuildinTypes types, uint v, Location loc) + : this (types.UInt, v, loc) + { + } + + public UIntConstant (TypeSpec type, uint v, Location loc) + : base (type, loc) { - type = TypeManager.uint32_type; - eclass = ExprClass.Value; Value = v; } - 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 () @@ -1067,9 +1208,14 @@ namespace Mono.CSharp { return Value; } + public override long GetValueAsLong () + { + return Value; + } + public override Constant Increment () { - return new UIntConstant (checked(Value + 1), loc); + return new UIntConstant (type, checked(Value + 1), loc); } public override bool IsDefaultValue { @@ -1083,65 +1229,67 @@ 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) + switch (target_type.BuildinType) { + case BuildinTypeSpec.Type.Byte: + if (in_checked_context) { + if (Value < 0 || Value > byte.MaxValue) throw new OverflowException (); } - return new ByteConstant ((byte) Value, Location); - } - if (target_type == TypeManager.sbyte_type) { - if (in_checked_context){ + return new ByteConstant (target_type, (byte) Value, Location); + case BuildinTypeSpec.Type.SByte: + if (in_checked_context) { if (Value > SByte.MaxValue) throw new OverflowException (); } - return new SByteConstant ((sbyte) Value, Location); - } - if (target_type == TypeManager.short_type) { - if (in_checked_context){ + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuildinTypeSpec.Type.Short: + if (in_checked_context) { if (Value > Int16.MaxValue) throw new OverflowException (); } - return new ShortConstant ((short) Value, Location); - } - if (target_type == TypeManager.ushort_type) { - if (in_checked_context){ + return new ShortConstant (target_type, (short) Value, Location); + case BuildinTypeSpec.Type.UShort: + if (in_checked_context) { if (Value < UInt16.MinValue || Value > UInt16.MaxValue) throw new OverflowException (); } - return new UShortConstant ((ushort) Value, Location); - } - if (target_type == TypeManager.int32_type) { - if (in_checked_context){ + return new UShortConstant (target_type, (ushort) Value, Location); + case BuildinTypeSpec.Type.Int: + if (in_checked_context) { if (Value > Int32.MaxValue) throw new OverflowException (); } - return new IntConstant ((int) Value, Location); - } - if (target_type == TypeManager.int64_type) - return new LongConstant ((long) Value, Location); - if (target_type == TypeManager.uint64_type) - return new ULongConstant ((ulong) Value, Location); - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) Value, Location); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) Value, Location); - if (target_type == TypeManager.char_type) { - if (in_checked_context){ + return new IntConstant (target_type, (int) Value, Location); + case BuildinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuildinTypeSpec.Type.ULong: + return new ULongConstant (target_type, (ulong) Value, Location); + case BuildinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuildinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuildinTypeSpec.Type.Char: + if (in_checked_context) { if (Value < Char.MinValue || Value > Char.MaxValue) throw new OverflowException (); } - return new CharConstant ((char) Value, Location); + return new CharConstant (target_type, (char) Value, Location); + case BuildinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) Value, Location); return null; } @@ -1151,39 +1299,25 @@ namespace Mono.CSharp { public class LongConstant : IntegralConstant { public readonly long Value; - public LongConstant (long v, Location loc): - base (loc) + public LongConstant (BuildinTypes types, long v, Location loc) + : this (types.Long, v, loc) { - type = TypeManager.int64_type; - eclass = ExprClass.Value; - Value = v; } - public override void Emit (EmitContext ec) + public LongConstant (TypeSpec type, long v, Location loc) + : base (type, loc) { - EmitLong (ec.ig, Value); + Value = v; } - 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 () @@ -1191,9 +1325,14 @@ namespace Mono.CSharp { return Value; } + public override long GetValueAsLong () + { + return Value; + } + public override Constant Increment () { - return new LongConstant (checked(Value + 1), loc); + return new LongConstant (type, checked(Value + 1), loc); } public override bool IsDefaultValue { @@ -1207,81 +1346,81 @@ 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){ + switch (target_type.BuildinType) { + case BuildinTypeSpec.Type.Byte: + if (in_checked_context) { if (Value < Byte.MinValue || Value > Byte.MaxValue) throw new OverflowException (); } - return new ByteConstant ((byte) Value, Location); - } - if (target_type == TypeManager.sbyte_type) { - if (in_checked_context){ + return new ByteConstant (target_type, (byte) Value, Location); + case BuildinTypeSpec.Type.SByte: + if (in_checked_context) { if (Value < SByte.MinValue || Value > SByte.MaxValue) throw new OverflowException (); } - return new SByteConstant ((sbyte) Value, Location); - } - if (target_type == TypeManager.short_type) { - if (in_checked_context){ + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuildinTypeSpec.Type.Short: + if (in_checked_context) { if (Value < Int16.MinValue || Value > Int16.MaxValue) throw new OverflowException (); } - return new ShortConstant ((short) Value, Location); - } - if (target_type == TypeManager.ushort_type) { - if (in_checked_context){ + return new ShortConstant (target_type, (short) Value, Location); + case BuildinTypeSpec.Type.UShort: + if (in_checked_context) { if (Value < UInt16.MinValue || Value > UInt16.MaxValue) throw new OverflowException (); } - return new UShortConstant ((ushort) Value, Location); - } - if (target_type == TypeManager.int32_type) { - if (in_checked_context){ + return new UShortConstant (target_type, (ushort) Value, Location); + case BuildinTypeSpec.Type.Int: + if (in_checked_context) { if (Value < Int32.MinValue || Value > Int32.MaxValue) throw new OverflowException (); } - return new IntConstant ((int) Value, Location); - } - if (target_type == TypeManager.uint32_type) { - if (in_checked_context){ + return new IntConstant (target_type, (int) Value, Location); + case BuildinTypeSpec.Type.UInt: + if (in_checked_context) { if (Value < UInt32.MinValue || Value > UInt32.MaxValue) throw new OverflowException (); } - return new UIntConstant ((uint) Value, Location); - } - if (target_type == TypeManager.uint64_type) { + return new UIntConstant (target_type, (uint) Value, Location); + case BuildinTypeSpec.Type.ULong: if (in_checked_context && Value < 0) throw new OverflowException (); - return new ULongConstant ((ulong) Value, Location); - } - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) Value, Location); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) Value, Location); - if (target_type == TypeManager.char_type) { - if (in_checked_context){ + return new ULongConstant (target_type, (ulong) Value, Location); + case BuildinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuildinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuildinTypeSpec.Type.Char: + if (in_checked_context) { if (Value < Char.MinValue || Value > Char.MaxValue) throw new OverflowException (); } - return new CharConstant ((char) Value, Location); + return new CharConstant (target_type, (char) Value, Location); + case BuildinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) Value, Location); return null; } - public override Constant ConvertImplicitly (Type type) + public override Constant ConvertImplicitly (TypeSpec type) { - if (Value >= 0 && type == TypeManager.uint64_type) { - return new ULongConstant ((ulong) Value, loc); + if (Value >= 0 && type.BuildinType == BuildinTypeSpec.Type.ULong) { + return new ULongConstant (type, (ulong) Value, loc); } return base.ConvertImplicitly (type); @@ -1291,24 +1430,25 @@ namespace Mono.CSharp { public class ULongConstant : IntegralConstant { public readonly ulong Value; - public ULongConstant (ulong v, Location loc): - base (loc) + public ULongConstant (BuildinTypes types, ulong v, Location loc) + : this (types.ULong, v, loc) { - type = TypeManager.uint64_type; - eclass = ExprClass.Value; - Value = v; } - public override void Emit (EmitContext ec) + public ULongConstant (TypeSpec type, ulong v, Location loc) + : base (type, loc) { - ILGenerator ig = ec.ig; + Value = v; + } - LongLiteral.EmitLong (ig, unchecked ((long) Value)); + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + 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 () @@ -1316,9 +1456,14 @@ namespace Mono.CSharp { return Value; } + public override long GetValueAsLong () + { + return (long) Value; + } + public override Constant Increment () { - return new ULongConstant (checked(Value + 1), loc); + return new ULongConstant (type, checked(Value + 1), loc); } public override bool IsDefaultValue { @@ -1332,59 +1477,59 @@ 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) { + switch (target_type.BuildinType) { + case BuildinTypeSpec.Type.Byte: if (in_checked_context && Value > Byte.MaxValue) throw new OverflowException (); - return new ByteConstant ((byte) Value, Location); - } - if (target_type == TypeManager.sbyte_type) { + return new ByteConstant (target_type, (byte) Value, Location); + case BuildinTypeSpec.Type.SByte: if (in_checked_context && Value > ((ulong) SByte.MaxValue)) throw new OverflowException (); - return new SByteConstant ((sbyte) Value, Location); - } - if (target_type == TypeManager.short_type) { + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuildinTypeSpec.Type.Short: if (in_checked_context && Value > ((ulong) Int16.MaxValue)) throw new OverflowException (); - return new ShortConstant ((short) Value, Location); - } - if (target_type == TypeManager.ushort_type) { + return new ShortConstant (target_type, (short) Value, Location); + case BuildinTypeSpec.Type.UShort: if (in_checked_context && Value > UInt16.MaxValue) throw new OverflowException (); - return new UShortConstant ((ushort) Value, Location); - } - if (target_type == TypeManager.int32_type) { + return new UShortConstant (target_type, (ushort) Value, Location); + case BuildinTypeSpec.Type.Int: if (in_checked_context && Value > UInt32.MaxValue) throw new OverflowException (); - return new IntConstant ((int) Value, Location); - } - if (target_type == TypeManager.uint32_type) { - if (in_checked_context && Value > UInt32.MaxValue) + return new IntConstant (target_type, (int) Value, Location); + case BuildinTypeSpec.Type.UInt: + if (in_checked_context && Value > UInt32.MaxValue) throw new OverflowException (); - return new UIntConstant ((uint) Value, Location); - } - if (target_type == TypeManager.int64_type) { + return new UIntConstant (target_type, (uint) Value, Location); + case BuildinTypeSpec.Type.Long: if (in_checked_context && Value > Int64.MaxValue) throw new OverflowException (); - return new LongConstant ((long) Value, Location); - } - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) Value, Location); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) Value, Location); - if (target_type == TypeManager.char_type) { + return new LongConstant (target_type, (long) Value, Location); + case BuildinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuildinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuildinTypeSpec.Type.Char: if (in_checked_context && Value > Char.MaxValue) throw new OverflowException (); - return new CharConstant ((char) Value, Location); + return new CharConstant (target_type, (char) Value, Location); + case BuildinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) Value, Location); return null; } @@ -1392,24 +1537,30 @@ namespace Mono.CSharp { } public class FloatConstant : Constant { - public float Value; + public readonly float Value; - public FloatConstant (float v, Location loc): - base (loc) + public FloatConstant (BuildinTypes types, float v, Location loc) + : this (types.Float, v, loc) { - type = TypeManager.float_type; + } + + public FloatConstant (TypeSpec type, float v, Location loc) + : base (loc) + { + this.type = type; eclass = ExprClass.Value; + Value = v; } - 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 () @@ -1417,9 +1568,14 @@ namespace Mono.CSharp { return Value; } - public override Constant Increment () + public override string GetValueAsLiteral () { - return new FloatConstant (checked(Value + 1), loc); + return Value.ToString (); + } + + public override long GetValueAsLong () + { + throw new NotSupportedException (); } public override bool IsDefaultValue { @@ -1434,100 +1590,100 @@ 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){ - if (Value < byte.MinValue || Value > byte.MaxValue) + switch (target_type.BuildinType) { + case BuildinTypeSpec.Type.Byte: + if (in_checked_context) { + if (Value < byte.MinValue || Value > byte.MaxValue || float.IsNaN (Value)) throw new OverflowException (); } - return new ByteConstant ((byte) Value, Location); - } - if (target_type == TypeManager.sbyte_type) { - if (in_checked_context){ - if (Value < sbyte.MinValue || Value > sbyte.MaxValue) + return new ByteConstant (target_type, (byte) Value, Location); + case BuildinTypeSpec.Type.SByte: + if (in_checked_context) { + if (Value < sbyte.MinValue || Value > sbyte.MaxValue || float.IsNaN (Value)) throw new OverflowException (); } - return new SByteConstant ((sbyte) Value, Location); - } - if (target_type == TypeManager.short_type) { - if (in_checked_context){ - if (Value < short.MinValue || Value > short.MaxValue) + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuildinTypeSpec.Type.Short: + if (in_checked_context) { + if (Value < short.MinValue || Value > short.MaxValue || float.IsNaN (Value)) throw new OverflowException (); } - return new ShortConstant ((short) Value, Location); - } - if (target_type == TypeManager.ushort_type) { - if (in_checked_context){ - if (Value < ushort.MinValue || Value > ushort.MaxValue) + return new ShortConstant (target_type, (short) Value, Location); + case BuildinTypeSpec.Type.UShort: + if (in_checked_context) { + if (Value < ushort.MinValue || Value > ushort.MaxValue || float.IsNaN (Value)) throw new OverflowException (); } - return new UShortConstant ((ushort) Value, Location); - } - if (target_type == TypeManager.int32_type) { - if (in_checked_context){ - if (Value < int.MinValue || Value > int.MaxValue) + return new UShortConstant (target_type, (ushort) Value, Location); + case BuildinTypeSpec.Type.Int: + if (in_checked_context) { + if (Value < int.MinValue || Value > int.MaxValue || float.IsNaN (Value)) throw new OverflowException (); } - return new IntConstant ((int) Value, Location); - } - if (target_type == TypeManager.uint32_type) { - if (in_checked_context){ - if (Value < uint.MinValue || Value > uint.MaxValue) + return new IntConstant (target_type, (int) Value, Location); + case BuildinTypeSpec.Type.UInt: + if (in_checked_context) { + if (Value < uint.MinValue || Value > uint.MaxValue || float.IsNaN (Value)) throw new OverflowException (); } - return new UIntConstant ((uint) Value, Location); - } - if (target_type == TypeManager.int64_type) { - if (in_checked_context){ - if (Value < long.MinValue || Value > long.MaxValue) + return new UIntConstant (target_type, (uint) Value, Location); + case BuildinTypeSpec.Type.Long: + if (in_checked_context) { + if (Value < long.MinValue || Value > long.MaxValue || float.IsNaN (Value)) throw new OverflowException (); } - return new LongConstant ((long) Value, Location); - } - if (target_type == TypeManager.uint64_type) { - if (in_checked_context){ - if (Value < ulong.MinValue || Value > ulong.MaxValue) + return new LongConstant (target_type, (long) Value, Location); + case BuildinTypeSpec.Type.ULong: + if (in_checked_context) { + if (Value < ulong.MinValue || Value > ulong.MaxValue || float.IsNaN (Value)) throw new OverflowException (); } - return new ULongConstant ((ulong) Value, Location); - } - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double) Value, Location); - if (target_type == TypeManager.char_type) { - if (in_checked_context){ - if (Value < (float) char.MinValue || Value > (float) char.MaxValue) + return new ULongConstant (target_type, (ulong) Value, Location); + case BuildinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuildinTypeSpec.Type.Char: + if (in_checked_context) { + if (Value < (float) char.MinValue || Value > (float) char.MaxValue || float.IsNaN (Value)) throw new OverflowException (); } - return new CharConstant ((char) Value, Location); + return new CharConstant (target_type, (char) Value, Location); + case BuildinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) Value, Location); return null; } } - public class DoubleConstant : Constant { - public double Value; + public class DoubleConstant : Constant + { + public readonly double Value; + + public DoubleConstant (BuildinTypes types, double v, Location loc) + : this (types.Double, v, loc) + { + } - public DoubleConstant (double v, Location loc): - base (loc) + public DoubleConstant (TypeSpec type, double v, Location loc) + : base (loc) { - type = TypeManager.double_type; + this.type = type; eclass = ExprClass.Value; + Value = v; } - 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 () @@ -1535,9 +1691,14 @@ namespace Mono.CSharp { return Value; } - public override Constant Increment () + public override string GetValueAsLiteral () { - return new DoubleConstant (checked(Value + 1), loc); + return Value.ToString (); + } + + public override long GetValueAsLong () + { + throw new NotSupportedException (); } public override bool IsDefaultValue { @@ -1552,75 +1713,68 @@ 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){ - if (Value < Byte.MinValue || Value > Byte.MaxValue) + switch (target_type.BuildinType) { + case BuildinTypeSpec.Type.Byte: + if (in_checked_context) { + if (Value < Byte.MinValue || Value > Byte.MaxValue || double.IsNaN (Value)) throw new OverflowException (); } - return new ByteConstant ((byte) Value, Location); - } - if (target_type == TypeManager.sbyte_type) { - if (in_checked_context){ - if (Value < SByte.MinValue || Value > SByte.MaxValue) + return new ByteConstant (target_type, (byte) Value, Location); + case BuildinTypeSpec.Type.SByte: + if (in_checked_context) { + if (Value < SByte.MinValue || Value > SByte.MaxValue || double.IsNaN (Value)) throw new OverflowException (); } - return new SByteConstant ((sbyte) Value, Location); - } - if (target_type == TypeManager.short_type) { - if (in_checked_context){ - if (Value < short.MinValue || Value > short.MaxValue) + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuildinTypeSpec.Type.Short: + if (in_checked_context) { + if (Value < short.MinValue || Value > short.MaxValue || double.IsNaN (Value)) throw new OverflowException (); } - return new ShortConstant ((short) Value, Location); - } - if (target_type == TypeManager.ushort_type) { - if (in_checked_context){ - if (Value < ushort.MinValue || Value > ushort.MaxValue) + return new ShortConstant (target_type, (short) Value, Location); + case BuildinTypeSpec.Type.UShort: + if (in_checked_context) { + if (Value < ushort.MinValue || Value > ushort.MaxValue || double.IsNaN (Value)) throw new OverflowException (); } - return new UShortConstant ((ushort) Value, Location); - } - if (target_type == TypeManager.int32_type) { - if (in_checked_context){ - if (Value < int.MinValue || Value > int.MaxValue) + return new UShortConstant (target_type, (ushort) Value, Location); + case BuildinTypeSpec.Type.Int: + if (in_checked_context) { + if (Value < int.MinValue || Value > int.MaxValue || double.IsNaN (Value)) throw new OverflowException (); } - return new IntConstant ((int) Value, Location); - } - if (target_type == TypeManager.uint32_type) { - if (in_checked_context){ - if (Value < uint.MinValue || Value > uint.MaxValue) + return new IntConstant (target_type, (int) Value, Location); + case BuildinTypeSpec.Type.UInt: + if (in_checked_context) { + if (Value < uint.MinValue || Value > uint.MaxValue || double.IsNaN (Value)) throw new OverflowException (); } - return new UIntConstant ((uint) Value, Location); - } - if (target_type == TypeManager.int64_type) { - if (in_checked_context){ - if (Value < long.MinValue || Value > long.MaxValue) + return new UIntConstant (target_type, (uint) Value, Location); + case BuildinTypeSpec.Type.Long: + if (in_checked_context) { + if (Value < long.MinValue || Value > long.MaxValue || double.IsNaN (Value)) throw new OverflowException (); } - return new LongConstant ((long) Value, Location); - } - if (target_type == TypeManager.uint64_type) { - if (in_checked_context){ - if (Value < ulong.MinValue || Value > ulong.MaxValue) + return new LongConstant (target_type, (long) Value, Location); + case BuildinTypeSpec.Type.ULong: + if (in_checked_context) { + if (Value < ulong.MinValue || Value > ulong.MaxValue || double.IsNaN (Value)) throw new OverflowException (); } - return new ULongConstant ((ulong) Value, Location); - } - if (target_type == TypeManager.float_type) - return new FloatConstant ((float) Value, Location); - if (target_type == TypeManager.char_type) { - if (in_checked_context){ - if (Value < (double) char.MinValue || Value > (double) char.MaxValue) + return new ULongConstant (target_type, (ulong) Value, Location); + case BuildinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuildinTypeSpec.Type.Char: + if (in_checked_context) { + if (Value < (double) char.MinValue || Value > (double) char.MaxValue || double.IsNaN (Value)) throw new OverflowException (); } - return new CharConstant ((char) Value, Location); + return new CharConstant (target_type, (char) Value, Location); + case BuildinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) Value, Location); return null; } @@ -1630,77 +1784,65 @@ namespace Mono.CSharp { public class DecimalConstant : Constant { public readonly decimal Value; - public DecimalConstant (decimal d, Location loc): - base (loc) + public DecimalConstant (BuildinTypes types, decimal d, Location loc) + : this (types.Decimal, d, loc) { - type = TypeManager.decimal_type; - eclass = ExprClass.Value; - Value = d; } - override public string AsString () + public DecimalConstant (TypeSpec type, decimal d, Location loc) + : base (loc) { - return Value.ToString (); - } + this.type = type; + eclass = ExprClass.Value; - public override object GetValue () - { - return (object) Value; + Value = d; } public override void Emit (EmitContext ec) { - ILGenerator ig = ec.ig; + MethodSpec m; - int [] words = Decimal.GetBits (Value); + int [] words = decimal.GetBits (Value); int power = (words [3] >> 16) & 0xff; - if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue) - { - if (TypeManager.void_decimal_ctor_int_arg == null) { - TypeManager.void_decimal_ctor_int_arg = TypeManager.GetPredefinedConstructor ( - TypeManager.decimal_type, loc, TypeManager.int32_type); - - if (TypeManager.void_decimal_ctor_int_arg == null) + if (power == 0) { + if (Value <= int.MaxValue && Value >= int.MinValue) { + m = ec.Module.PredefinedMembers.DecimalCtorInt.Resolve (loc); + if (m == null) { return; + } + + ec.EmitInt ((int) Value); + ec.Emit (OpCodes.Newobj, m); + return; } - IntConstant.EmitInt (ig, (int)Value); - ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg); - return; - } + if (Value <= long.MaxValue && Value >= long.MinValue) { + m = ec.Module.PredefinedMembers.DecimalCtorLong.Resolve (loc); + if (m == null) { + return; + } - - // - // FIXME: we could optimize this, and call a better - // constructor - // + ec.EmitLong ((long) Value); + ec.Emit (OpCodes.Newobj, m); + 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); - - if (TypeManager.void_decimal_ctor_five_args == null) { - TypeManager.void_decimal_ctor_five_args = TypeManager.GetPredefinedConstructor ( - TypeManager.decimal_type, loc, TypeManager.int32_type, TypeManager.int32_type, - TypeManager.int32_type, TypeManager.bool_type, TypeManager.byte_type); + ec.EmitInt (power); - if (TypeManager.void_decimal_ctor_five_args == null) - return; + m = ec.Module.PredefinedMembers.DecimalCtor.Resolve (loc); + if (m != null) { + ec.Emit (OpCodes.Newobj, m); } - - ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args); - } - - public override Constant Increment () - { - return new DecimalConstant (checked (Value + 1), loc); } public override bool IsDefaultValue { @@ -1715,62 +1857,89 @@ namespace Mono.CSharp { } } - public override Constant ConvertExplicitly (bool in_checked_context, Type target_type) - { - if (target_type == TypeManager.sbyte_type) - return new SByteConstant ((sbyte)Value, loc); - if (target_type == TypeManager.byte_type) - return new ByteConstant ((byte)Value, loc); - if (target_type == TypeManager.short_type) - return new ShortConstant ((short)Value, loc); - if (target_type == TypeManager.ushort_type) - return new UShortConstant ((ushort)Value, loc); - if (target_type == TypeManager.int32_type) - return new IntConstant ((int)Value, loc); - if (target_type == TypeManager.uint32_type) - return new UIntConstant ((uint)Value, loc); - if (target_type == TypeManager.int64_type) - return new LongConstant ((long)Value, loc); - if (target_type == TypeManager.uint64_type) - return new ULongConstant ((ulong)Value, loc); - if (target_type == TypeManager.char_type) - return new CharConstant ((char)Value, loc); - if (target_type == TypeManager.float_type) - return new FloatConstant ((float)Value, loc); - if (target_type == TypeManager.double_type) - return new DoubleConstant ((double)Value, loc); + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuildinType) { + case BuildinTypeSpec.Type.SByte: + return new SByteConstant (target_type, (sbyte) Value, loc); + case BuildinTypeSpec.Type.Byte: + return new ByteConstant (target_type, (byte) Value, loc); + case BuildinTypeSpec.Type.Short: + return new ShortConstant (target_type, (short) Value, loc); + case BuildinTypeSpec.Type.UShort: + return new UShortConstant (target_type, (ushort) Value, loc); + case BuildinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, loc); + case BuildinTypeSpec.Type.UInt: + return new UIntConstant (target_type, (uint) Value, loc); + case BuildinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, loc); + case BuildinTypeSpec.Type.ULong: + return new ULongConstant (target_type, (ulong) Value, loc); + case BuildinTypeSpec.Type.Char: + return new CharConstant (target_type, (char) Value, loc); + case BuildinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, loc); + case BuildinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, loc); + } return null; } + public override object GetValue () + { + return Value; + } + + public override string GetValueAsLiteral () + { + return Value.ToString () + "M"; + } + + public override long GetValueAsLong () + { + throw new NotSupportedException (); + } } public class StringConstant : Constant { public readonly string Value; - public StringConstant (string s, Location loc): - base (loc) + public StringConstant (BuildinTypes types, string s, Location loc) + : this (types.String, s, loc) { - type = TypeManager.string_type; + } + + public StringConstant (TypeSpec type, string s, Location loc) + : base (loc) + { + this.type = type; eclass = ExprClass.Value; + Value = s; } - // FIXME: Escape the string. - override public string AsString () + public override object GetValue () + { + return Value; + } + + public override string GetValueAsLiteral () { + // FIXME: Escape the string. return "\"" + Value + "\""; } - public override object GetValue () + public override long GetValueAsLong () { - return Value; + throw new NotSupportedException (); } public override void Emit (EmitContext ec) { if (Value == null) { - ec.ig.Emit (OpCodes.Ldnull); + ec.Emit (OpCodes.Ldnull); return; } @@ -1778,22 +1947,27 @@ 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 && ec.TypeContainer.TypeBuilder != TypeManager.string_type) { - if (TypeManager.string_empty == null) - TypeManager.string_empty = TypeManager.GetPredefinedField (TypeManager.string_type, "Empty", loc); - - if (TypeManager.string_empty != null) { - ec.ig.Emit (OpCodes.Ldsfld, TypeManager.string_empty); - return; + if (Value.Length == 0 && ec.Module.Compiler.Settings.Optimize) { + var string_type = ec.BuildinTypes.String; + if (ec.CurrentType != string_type) { + var m = ec.Module.PredefinedMembers.StringEmpty.Get (); + if (m != null) { + ec.Emit (OpCodes.Ldsfld, m); + return; + } } } - ec.ig.Emit (OpCodes.Ldstr, Value); + ec.Emit (OpCodes.Ldstr, Value); } - public override Constant Increment () + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) { - throw new NotSupportedException (); + // cast to object + if (type != targetType) + enc.Encode (type); + + enc.Encode (Value); } public override bool IsDefaultValue { @@ -1808,40 +1982,202 @@ namespace Mono.CSharp { } } - public override Constant ConvertExplicitly (bool in_checked_context, Type target_type) + public override bool IsNull { + get { + return IsDefaultValue; + } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { return null; } } + // + // Null constant can have its own type, think of `default (Foo)' + // + public class NullConstant : Constant + { + public NullConstant (TypeSpec type, Location loc) + : base (loc) + { + eclass = ExprClass.Value; + this.type = type; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + if (type == InternalType.NullLiteral || type.BuildinType == BuildinTypeSpec.Type.Object) { + // 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); + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + // Type it as string cast + if (targetType.BuildinType == BuildinTypeSpec.Type.Object) + enc.Encode (rc.Module.Compiler.BuildinTypes.String); + + 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.Emit (OpCodes.Ldnull); + + // Only to make verifier happy + if (type.IsGenericParameter) + ec.Emit (OpCodes.Unbox_Any, type); + } + + public override string ExprClassName { + get { + return GetSignatureForError (); + } + } + + public override Constant ConvertExplicitly (bool inCheckedContext, TypeSpec targetType) + { + if (targetType.IsPointer) { + if (IsLiteral || this is NullPointer) + return new NullPointer (targetType, loc); + + return null; + } + + // Exlude internal compiler types + if (targetType.Kind == MemberKind.InternalCompilerType && targetType.BuildinType != BuildinTypeSpec.Type.Dynamic) + return null; + + if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType)) + return null; + + if (TypeManager.IsReferenceType (targetType)) + return new NullConstant (targetType, loc); + + if (targetType.IsNullableType) + return Nullable.LiftedNull.Create (targetType, loc); + + return null; + } + + public override Constant ConvertImplicitly (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 long GetValueAsLong () + { + throw new NotSupportedException (); + } + + public override bool IsDefaultValue { + get { return true; } + } + + public override bool IsNegative { + get { return false; } + } + + public override bool IsNull { + get { return true; } + } + + public override bool IsZeroInteger { + get { return true; } + } + } + + + // + // A null constant in a pointer context + // + class NullPointer : NullConstant + { + public NullPointer (TypeSpec type, Location loc) + : base (type, loc) + { + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Error_PointerInsideExpressionTree (ec); + return base.CreateExpressionTree (ec); + } + + public override void Emit (EmitContext ec) + { + // + // Emits null pointer + // + ec.Emit (OpCodes.Ldc_I4_0); + ec.Emit (OpCodes.Conv_U); + } + } + /// /// The value is constant, but when emitted has a side effect. This is /// used by BitwiseAnd to ensure that the second expression is invoked /// regardless of the value of the left side. /// - public class SideEffectConstant : Constant { - public Constant value; + public readonly Constant value; Expression side_effect; - public SideEffectConstant (Constant value, Expression side_effect, Location loc) : base (loc) + public SideEffectConstant (Constant value, Expression side_effect, Location loc) + : base (loc) { this.value = value; + type = value.Type; + eclass = ExprClass.Value; + while (side_effect is SideEffectConstant) side_effect = ((SideEffectConstant) side_effect).side_effect; this.side_effect = side_effect; - eclass = ExprClass.Value; - type = value.Type; } - public override string AsString () + public override object GetValue () { - return value.AsString (); + return value.GetValue (); } - public override object GetValue () + public override string GetValueAsLiteral () { - return value.GetValue (); + return value.GetValueAsLiteral (); + } + + public override long GetValueAsLong () + { + return value.GetValueAsLong (); } public override void Emit (EmitContext ec) @@ -1860,11 +2196,6 @@ namespace Mono.CSharp { get { return value.IsDefaultValue; } } - public override Constant Increment () - { - throw new NotSupportedException (); - } - public override bool IsNegative { get { return value.IsNegative; } } @@ -1873,10 +2204,16 @@ 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); + if (new_value == null) + return null; + + var c = new SideEffectConstant (new_value, side_effect, new_value.Location); + c.type = target_type; + c.eclass = eclass; + return c; } } }