X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fconstant.cs;h=397d72c9a4ae7653be65733999a337aaf1567695;hb=3f9310e59b924a8ef63dfef6c7f3c72935ac8f21;hp=81d2c9604c33482226971554f6c8f736937bc64d;hpb=e097a6443206bcdf9866e0c65883ece765144d02;p=mono.git diff --git a/mcs/mcs/constant.cs b/mcs/mcs/constant.cs index 81d2c9604c3..397d72c9a4a 100644 --- a/mcs/mcs/constant.cs +++ b/mcs/mcs/constant.cs @@ -3,13 +3,15 @@ // // Author: // Miguel de Icaza (miguel@ximian.com) -// Marek Safar (marek.safar@seznam.cz) +// Marek Safar (marek.safar@gmail.com) // // Copyright 2001-2003 Ximian, Inc. // Copyright 2003-2008 Novell, Inc. +// Copyright 2011-2013 Xamarin Inc // using System; +using System.Globalization; #if STATIC using IKVM.Reflection.Emit; @@ -22,7 +24,9 @@ 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) { @@ -40,6 +44,8 @@ namespace Mono.CSharp { /// public abstract object GetValue (); + public abstract long GetValueAsLong (); + public abstract string GetValueAsLiteral (); #if !STATIC @@ -52,113 +58,119 @@ namespace Mono.CSharp { } #endif - public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) + public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl) { if (!expl && IsLiteral && - (TypeManager.IsPrimitiveType (target) || type == TypeManager.decimal_type) && - (TypeManager.IsPrimitiveType (type) || type == TypeManager.decimal_type)) { + BuiltinTypeSpec.IsPrimitiveTypeOrDecimal (target) && + BuiltinTypeSpec.IsPrimitiveTypeOrDecimal (type)) { ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'", - GetValueAsLiteral (), TypeManager.CSharpName (target)); + GetValueAsLiteral (), target.GetSignatureForError ()); } else { - base.Error_ValueCannotBeConverted (ec, loc, target, expl); + base.Error_ValueCannotBeConverted (ec, target, expl); } } public Constant ImplicitConversionRequired (ResolveContext ec, TypeSpec type, Location loc) { - Constant c = ConvertImplicitly (ec, type); + Constant c = ConvertImplicitly (type); if (c == null) - Error_ValueCannotBeConverted (ec, loc, type, false); + Error_ValueCannotBeConverted (ec, type, false); return c; } - public virtual Constant ConvertImplicitly (ResolveContext rc, TypeSpec type) + public override bool ContainsEmitWithAwait () + { + return false; + } + + public virtual Constant ConvertImplicitly (TypeSpec type) { if (this.type == type) return this; - if (Convert.ImplicitNumericConversion (this, type) == null) + if (!Convert.ImplicitNumericConversionExists (this.type, type)) 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 // reached, by calling Convert.ImplicitStandardConversionExists // throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'", - TypeManager.CSharpName (Type), TypeManager.CSharpName (type)); + Type.GetSignatureForError (), type.GetSignatureForError ()); } - return CreateConstant (rc, type, constant_value, loc); + return CreateConstantFromValue (type, constant_value, loc); } // // Returns a constant instance based on Type // - public static Constant CreateConstant (ResolveContext rc, TypeSpec t, object v, Location loc) - { - return CreateConstantFromValue (t, v, loc).Resolve (rc); - } - public static Constant CreateConstantFromValue (TypeSpec 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)) { + switch (t.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + return new IntConstant (t, (int) v, loc); + case BuiltinTypeSpec.Type.String: + return new StringConstant (t, (string) v, loc); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (t, (uint) v, loc); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (t, (long) v, loc); + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (t, (ulong) v, loc); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (t, (float) v, loc); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (t, (double) v, loc); + case BuiltinTypeSpec.Type.Short: + return new ShortConstant (t, (short) v, loc); + case BuiltinTypeSpec.Type.UShort: + return new UShortConstant (t, (ushort) v, loc); + case BuiltinTypeSpec.Type.SByte: + return new SByteConstant (t, (sbyte) v, loc); + case BuiltinTypeSpec.Type.Byte: + return new ByteConstant (t, (byte) v, loc); + case BuiltinTypeSpec.Type.Char: + return new CharConstant (t, (char) v, loc); + case BuiltinTypeSpec.Type.Bool: + return new BoolConstant (t, (bool) v, loc); + case BuiltinTypeSpec.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).Resolve (null), t); + return new EnumConstant (CreateConstantFromValue (real_type, v, loc), t); } + if (v == null) { - if (TypeManager.IsNullableType (t)) + if (t.IsNullableType) return Nullable.LiftedNull.Create (t, loc); - if (TypeManager.IsReferenceType (t)) + if (TypeSpec.IsReferenceType (t)) return new NullConstant (t, loc); } - throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'", - v, TypeManager.CSharpName (t)); +#if STATIC + throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'", v, t.GetSignatureForError ()); +#else + return null; +#endif } 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))); + args.Add (new Argument (new TypeOf (type, loc))); return CreateExpressionFactoryCall (ec, "Constant", args); } - /// /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type. /// It throws OverflowException @@ -166,46 +178,127 @@ namespace Mono.CSharp { // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS 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, TypeSpec target_type, Location loc) + // 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 { - return TryReduce (ec, target_type); + switch (targetType.BuiltinType) { + case BuiltinTypeSpec.Type.Bool: + return convert_value.ToBoolean (nfi); + case BuiltinTypeSpec.Type.Byte: + return convert_value.ToByte (nfi); + case BuiltinTypeSpec.Type.Char: + return convert_value.ToChar (nfi); + case BuiltinTypeSpec.Type.Short: + return convert_value.ToInt16 (nfi); + case BuiltinTypeSpec.Type.Int: + return convert_value.ToInt32 (nfi); + case BuiltinTypeSpec.Type.Long: + return convert_value.ToInt64 (nfi); + case BuiltinTypeSpec.Type.SByte: + return convert_value.ToSByte (nfi); + case BuiltinTypeSpec.Type.Decimal: + if (convert_value.GetType () == typeof (char)) + return (decimal) convert_value.ToInt32 (nfi); + return convert_value.ToDecimal (nfi); + case BuiltinTypeSpec.Type.Double: + if (convert_value.GetType () == typeof (char)) + return (double) convert_value.ToInt32 (nfi); + return convert_value.ToDouble (nfi); + case BuiltinTypeSpec.Type.Float: + if (convert_value.GetType () == typeof (char)) + return (float) convert_value.ToInt32 (nfi); + return convert_value.ToSingle (nfi); + case BuiltinTypeSpec.Type.String: + return convert_value.ToString (nfi); + case BuiltinTypeSpec.Type.UShort: + return convert_value.ToUInt16 (nfi); + case BuiltinTypeSpec.Type.UInt: + return convert_value.ToUInt32 (nfi); + case BuiltinTypeSpec.Type.ULong: + return convert_value.ToUInt64 (nfi); + case BuiltinTypeSpec.Type.Object: + return value; + } + } catch { } - catch (OverflowException) { - if (ec.ConstantCheckState && Type.BuildinType != BuildinTypeSpec.Type.Decimal) { + + error = true; + return null; + } + + protected override Expression DoResolve (ResolveContext rc) + { + return this; + } + + // + // Attempts to do a compile-time folding of a constant cast and handles + // error reporting for constant overlows only, on normal conversion + // errors returns null + // + public Constant Reduce (ResolveContext ec, TypeSpec target_type) + { + try { + return TryReduceConstant (ec, target_type); + } catch (OverflowException) { + if (ec.ConstantCheckState && Type.BuiltinType != BuiltinTypeSpec.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); + Error_ValueCannotBeConverted (ec, target_type, false); } - return New.Constantify (target_type, loc).Resolve (ec); + return New.Constantify (target_type, loc); } } - Constant TryReduce (ResolveContext ec, TypeSpec target_type) + public Constant TryReduce (ResolveContext rc, TypeSpec targetType) { - if (Type == target_type) + try { + return TryReduceConstant (rc, targetType); + } catch (OverflowException) { + return null; + } + } + + Constant TryReduceConstant (ResolveContext ec, TypeSpec target_type) + { + if (Type == target_type) { + // + // Reducing literal value produces a new constant. Syntactically 10 is not same as (int)10 + // + if (IsLiteral) + return CreateConstantFromValue (target_type, GetValue (), loc); + return this; + } Constant c; - if (TypeManager.IsEnumType (target_type)) { - c = TryReduce (ec, EnumSpec.GetUnderlyingType (target_type)); + if (target_type.IsEnum) { + c = TryReduceConstant (ec, EnumSpec.GetUnderlyingType (target_type)); if (c == null) return null; - return new EnumConstant (c, target_type).Resolve (ec); + return new EnumConstant (c, target_type); } - c = ConvertExplicitly (ec.ConstantCheckState, target_type); - if (c != null) - c = c.Resolve (ec); - - return c; + return ConvertExplicitly (ec.ConstantCheckState, target_type); } /// @@ -237,7 +330,13 @@ namespace Mono.CSharp { public virtual bool IsOneInteger { get { return false; } - } + } + + public override bool IsSideEffectFree { + get { + return true; + } + } // // Returns true iff 1) the stack type of this is one of Object, @@ -272,45 +371,32 @@ namespace Mono.CSharp { #endif } - public new Constant Resolve (ResolveContext rc) + public new bool Resolve (ResolveContext rc) { - if (eclass != ExprClass.Unresolved) - return this; - - // Resolved constant has to be still a constant - Constant c = (Constant) DoResolve (rc); - if (c == null) - return null; - - if ((c.eclass & ExprClass.Value) == 0) { - c.Error_UnexpectedKind (rc, ResolveFlags.VariableOrValue, loc); - return null; - } - - if (c.type == null) - throw new InternalErrorException ("Expression `{0}' did not set its type after Resolve", c.GetType ()); - - return c; + // It exists only as hint not to call Resolve on constants + return true; } } public abstract class IntegralConstant : Constant { - protected IntegralConstant (Location loc) : - base (loc) + protected IntegralConstant (TypeSpec type, Location loc) + : base (loc) { + this.type = type; + eclass = ExprClass.Value; } - public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) + public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl) { try { ConvertExplicitly (true, target); - base.Error_ValueCannotBeConverted (ec, loc, target, expl); + base.Error_ValueCannotBeConverted (ec, target, expl); } catch { ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'", - GetValue ().ToString (), TypeManager.CSharpName (target)); + GetValue ().ToString (), target.GetSignatureForError ()); } } @@ -324,18 +410,19 @@ namespace Mono.CSharp { public class BoolConstant : Constant { public readonly bool Value; - - public BoolConstant (bool val, Location loc): - base (loc) + + public BoolConstant (BuiltinTypes types, bool val, Location loc) + : this (types.Bool, val, loc) { - Value = val; } - - protected override Expression DoResolve (ResolveContext ec) + + public BoolConstant (TypeSpec type, bool val, Location loc) + : base (loc) { - type = TypeManager.bool_type; eclass = ExprClass.Value; - return this; + this.type = type; + + Value = val; } public override object GetValue () @@ -348,6 +435,11 @@ namespace Mono.CSharp { return Value ? "true" : "false"; } + public override long GetValueAsLong () + { + return Value ? 1 : 0; + } + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) { enc.Encode (Value); @@ -356,9 +448,9 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { if (Value) - ec.Emit (OpCodes.Ldc_I4_1); + ec.EmitInt (1); else - ec.Emit (OpCodes.Ldc_I4_0); + ec.EmitInt (0); } public override bool IsDefaultValue { @@ -384,11 +476,17 @@ namespace Mono.CSharp { } - public class ByteConstant : IntegralConstant { + public class ByteConstant : IntegralConstant + { public readonly byte Value; - public ByteConstant (byte v, Location loc): - base (loc) + public ByteConstant (BuiltinTypes types, byte v, Location loc) + : this (types.Byte, v, loc) + { + } + + public ByteConstant (TypeSpec type, byte v, Location loc) + : base (type, loc) { Value = v; } @@ -403,21 +501,19 @@ namespace Mono.CSharp { ec.EmitInt (Value); } - protected override Expression DoResolve (ResolveContext ec) + public override object GetValue () { - type = TypeManager.byte_type; - eclass = ExprClass.Value; - return this; + return Value; } - public override object GetValue () + 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 { @@ -444,33 +540,34 @@ namespace Mono.CSharp { public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { - if (target_type == TypeManager.sbyte_type) { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.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 BuiltinTypeSpec.Type.Short: + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.Type.UShort: + return new UShortConstant (target_type, (ushort) Value, Location); + case BuiltinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.Type.Char: + return new CharConstant (target_type, (char) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } return null; } @@ -480,17 +577,18 @@ namespace Mono.CSharp { public class CharConstant : Constant { public readonly char Value; - public CharConstant (char v, Location loc): - base (loc) + public CharConstant (BuiltinTypes types, char v, Location loc) + : this (types.Char, v, loc) { - Value = v; } - protected override Expression DoResolve (ResolveContext rc) + public CharConstant (TypeSpec type, char v, Location loc) + : base (loc) { - type = TypeManager.char_type; + this.type = type; eclass = ExprClass.Value; - return this; + + Value = v; } public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) @@ -537,6 +635,11 @@ namespace Mono.CSharp { return Value; } + public override long GetValueAsLong () + { + return Value; + } + public override string GetValueAsLiteral () { return "\"" + descape (Value) + "\""; @@ -560,61 +663,60 @@ namespace Mono.CSharp { public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { - if (target_type == TypeManager.byte_type) { - if (in_checked_context){ + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.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 (BuiltinTypes types, sbyte v, Location loc) + : this (types.SByte, v, loc) { - Value = v; } - protected override Expression DoResolve (ResolveContext rc) + public SByteConstant (TypeSpec type, sbyte v, Location loc) + : base (type, loc) { - type = TypeManager.sbyte_type; - eclass = ExprClass.Value; - return this; + Value = v; } public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) @@ -632,9 +734,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 { @@ -661,41 +768,40 @@ namespace Mono.CSharp { public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { - if (target_type == TypeManager.byte_type) { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.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 BuiltinTypeSpec.Type.Short: + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.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 BuiltinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.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 BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.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 BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.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 BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) Value, Location); return null; } @@ -705,17 +811,15 @@ namespace Mono.CSharp { public class ShortConstant : IntegralConstant { public readonly short Value; - public ShortConstant (short v, Location loc): - base (loc) + public ShortConstant (BuiltinTypes types, short v, Location loc) + : this (types.Short, v, loc) { - Value = v; } - protected override Expression DoResolve (ResolveContext rc) + public ShortConstant (TypeSpec type, short v, Location loc) + : base (type, loc) { - type = TypeManager.short_type; - eclass = ExprClass.Value; - return this; + Value = v; } public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) @@ -733,9 +837,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 { @@ -762,73 +871,68 @@ namespace Mono.CSharp { public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { - if (target_type == TypeManager.byte_type) { - if (in_checked_context){ + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.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 BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.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 BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.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 BuiltinTypeSpec.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 (BuiltinTypes types, ushort v, Location loc) + : this (types.UShort, v, loc) { - Value = v; } - protected override Expression DoResolve (ResolveContext rc) + public UShortConstant (TypeSpec type, ushort v, Location loc) + : base (type, loc) { - type = TypeManager.ushort_type; - eclass = ExprClass.Value; - return this; + Value = v; } public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) @@ -845,10 +949,15 @@ namespace Mono.CSharp { { 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 { @@ -875,67 +984,64 @@ namespace Mono.CSharp { public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { - if (target_type == TypeManager.byte_type) { - if (in_checked_context){ + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.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 BuiltinTypeSpec.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 (BuiltinTypes types, int v, Location loc) + : this (types.Int, v, loc) { - Value = v; } - protected override Expression DoResolve (ResolveContext rc) + public IntConstant (TypeSpec type, int v, Location loc) + : base (type, loc) { - type = TypeManager.int32_type; - eclass = ExprClass.Value; - return this; + Value = v; } public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) @@ -953,9 +1059,14 @@ namespace Mono.CSharp { return Value; } + 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 { @@ -982,75 +1093,70 @@ namespace Mono.CSharp { public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { - if (target_type == TypeManager.byte_type) { - if (in_checked_context){ + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.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 BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.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 BuiltinTypeSpec.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 (ResolveContext rc, TypeSpec type) + public override Constant ConvertImplicitly (TypeSpec type) { if (this.type == type) return this; Constant c = TryImplicitIntConversion (type); if (c != null) - return c.Resolve (rc); + return c; //.Resolve (rc); - return base.ConvertImplicitly (rc, type); + return base.ConvertImplicitly (type); } /// @@ -1060,39 +1166,41 @@ namespace Mono.CSharp { /// Constant TryImplicitIntConversion (TypeSpec target_type) { - if (target_type == TypeManager.sbyte_type) { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, loc); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, loc); + } return null; } @@ -1101,17 +1209,15 @@ namespace Mono.CSharp { public class UIntConstant : IntegralConstant { public readonly uint Value; - public UIntConstant (uint v, Location loc): - base (loc) + public UIntConstant (BuiltinTypes types, uint v, Location loc) + : this (types.UInt, v, loc) { - Value = v; } - protected override Expression DoResolve (ResolveContext rc) + public UIntConstant (TypeSpec type, uint v, Location loc) + : base (type, loc) { - type = TypeManager.uint32_type; - eclass = ExprClass.Value; - return this; + Value = v; } public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) @@ -1129,9 +1235,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 { @@ -1158,58 +1269,54 @@ namespace Mono.CSharp { public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { - if (target_type == TypeManager.byte_type) { - if (in_checked_context){ + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.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 BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) Value, Location); return null; } @@ -1219,17 +1326,15 @@ namespace Mono.CSharp { public class LongConstant : IntegralConstant { public readonly long Value; - public LongConstant (long v, Location loc): - base (loc) + public LongConstant (BuiltinTypes types, long v, Location loc) + : this (types.Long, v, loc) { - Value = v; } - protected override Expression DoResolve (ResolveContext rc) + public LongConstant (TypeSpec type, long v, Location loc) + : base (type, loc) { - type = TypeManager.int64_type; - eclass = ExprClass.Value; - return this; + Value = v; } public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) @@ -1247,9 +1352,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 { @@ -1276,94 +1386,86 @@ namespace Mono.CSharp { public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { - if (target_type == TypeManager.byte_type) { - if (in_checked_context){ + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.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 BuiltinTypeSpec.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 (ResolveContext rc, TypeSpec type) + public override Constant ConvertImplicitly (TypeSpec type) { - if (Value >= 0 && type == TypeManager.uint64_type) { - return new ULongConstant ((ulong) Value, loc).Resolve (rc); + if (Value >= 0 && type.BuiltinType == BuiltinTypeSpec.Type.ULong) { + return new ULongConstant (type, (ulong) Value, loc); } - return base.ConvertImplicitly (rc, type); + return base.ConvertImplicitly (type); } } public class ULongConstant : IntegralConstant { public readonly ulong Value; - public ULongConstant (ulong v, Location loc): - base (loc) + public ULongConstant (BuiltinTypes types, ulong v, Location loc) + : this (types.ULong, v, loc) { - Value = v; } - protected override Expression DoResolve (ResolveContext rc) + public ULongConstant (TypeSpec type, ulong v, Location loc) + : base (type, loc) { - type = TypeManager.uint64_type; - eclass = ExprClass.Value; - return this; + Value = v; } public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) @@ -1381,9 +1483,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 { @@ -1410,52 +1517,46 @@ namespace Mono.CSharp { public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { - if (target_type == TypeManager.byte_type) { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.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 BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.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 BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) Value, Location); return null; } @@ -1463,19 +1564,20 @@ namespace Mono.CSharp { } public class FloatConstant : Constant { - public float Value; + public readonly float Value; - public FloatConstant (float v, Location loc): - base (loc) + public FloatConstant (BuiltinTypes types, float v, Location loc) + : this (types.Float, v, loc) { - Value = v; } - protected override Expression DoResolve (ResolveContext rc) + public FloatConstant (TypeSpec type, float v, Location loc) + : base (loc) { - type = TypeManager.float_type; + this.type = type; eclass = ExprClass.Value; - return this; + + Value = v; } public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) @@ -1498,6 +1600,11 @@ namespace Mono.CSharp { return Value.ToString (); } + public override long GetValueAsLong () + { + throw new NotSupportedException (); + } + public override bool IsDefaultValue { get { return Value == 0; @@ -1512,93 +1619,88 @@ namespace Mono.CSharp { public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { - if (target_type == TypeManager.byte_type) { - if (in_checked_context){ + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.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){ + return new ByteConstant (target_type, (byte) Value, Location); + case BuiltinTypeSpec.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){ + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuiltinTypeSpec.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){ + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.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){ + return new UShortConstant (target_type, (ushort) Value, Location); + case BuiltinTypeSpec.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){ + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.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){ + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.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){ + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.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){ + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.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 BuiltinTypeSpec.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 (double v, Location loc): - base (loc) + public DoubleConstant (BuiltinTypes types, double v, Location loc) + : this (types.Double, v, loc) { - Value = v; } - protected override Expression DoResolve (ResolveContext rc) + public DoubleConstant (TypeSpec type, double v, Location loc) + : base (loc) { - type = TypeManager.double_type; + this.type = type; eclass = ExprClass.Value; - return this; + + Value = v; } public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) @@ -1621,6 +1723,11 @@ namespace Mono.CSharp { return Value.ToString (); } + public override long GetValueAsLong () + { + throw new NotSupportedException (); + } + public override bool IsDefaultValue { get { return Value == 0; @@ -1635,73 +1742,66 @@ namespace Mono.CSharp { public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { - if (target_type == TypeManager.byte_type) { - if (in_checked_context){ + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.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){ + return new ByteConstant (target_type, (byte) Value, Location); + case BuiltinTypeSpec.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){ + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuiltinTypeSpec.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){ + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.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){ + return new UShortConstant (target_type, (ushort) Value, Location); + case BuiltinTypeSpec.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){ + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.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){ + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.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){ + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.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){ + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.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 BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); } - if (target_type == TypeManager.decimal_type) - return new DecimalConstant ((decimal) Value, Location); return null; } @@ -1711,60 +1811,47 @@ namespace Mono.CSharp { public class DecimalConstant : Constant { public readonly decimal Value; - public DecimalConstant (decimal d, Location loc): - base (loc) + public DecimalConstant (BuiltinTypes types, decimal d, Location loc) + : this (types.Decimal, d, loc) { - Value = d; } - protected override Expression DoResolve (ResolveContext rc) + public DecimalConstant (TypeSpec type, decimal d, Location loc) + : base (loc) { - type = TypeManager.decimal_type; + this.type = type; eclass = ExprClass.Value; - return this; - } - - public override object GetValue () - { - return Value; - } - public override string GetValueAsLiteral () - { - return Value.ToString () + "M"; + Value = d; } public override void Emit (EmitContext ec) { + MethodSpec m; + int [] words = decimal.GetBits (Value); int power = (words [3] >> 16) & 0xff; if (power == 0) { if (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) - return; + m = ec.Module.PredefinedMembers.DecimalCtorInt.Resolve (loc); + if (m == null) { + return; } ec.EmitInt ((int) Value); - ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg); + ec.Emit (OpCodes.Newobj, m); return; } if (Value <= long.MaxValue && Value >= long.MinValue) { - if (TypeManager.void_decimal_ctor_long_arg == null) { - TypeManager.void_decimal_ctor_long_arg = TypeManager.GetPredefinedConstructor ( - TypeManager.decimal_type, loc, TypeManager.int64_type); - - if (TypeManager.void_decimal_ctor_long_arg == null) - return; + m = ec.Module.PredefinedMembers.DecimalCtorLong.Resolve (loc); + if (m == null) { + return; } ec.EmitLong ((long) Value); - ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_long_arg); + ec.Emit (OpCodes.Newobj, m); return; } } @@ -1779,16 +1866,10 @@ namespace Mono.CSharp { // power ec.EmitInt (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); - - if (TypeManager.void_decimal_ctor_five_args == null) - return; + m = ec.Module.PredefinedMembers.DecimalCtor.Resolve (loc); + if (m != null) { + ec.Emit (OpCodes.Newobj, m); } - - ec.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args); } public override bool IsDefaultValue { @@ -1805,48 +1886,65 @@ namespace Mono.CSharp { public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec 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); + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new SByteConstant (target_type, (sbyte) Value, loc); + case BuiltinTypeSpec.Type.Byte: + return new ByteConstant (target_type, (byte) Value, loc); + case BuiltinTypeSpec.Type.Short: + return new ShortConstant (target_type, (short) Value, loc); + case BuiltinTypeSpec.Type.UShort: + return new UShortConstant (target_type, (ushort) Value, loc); + case BuiltinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, loc); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (target_type, (uint) Value, loc); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, loc); + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (target_type, (ulong) Value, loc); + case BuiltinTypeSpec.Type.Char: + return new CharConstant (target_type, (char) Value, loc); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, loc); + case BuiltinTypeSpec.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 (BuiltinTypes types, string s, Location loc) + : this (types.String, s, loc) { - Value = s; } - protected override Expression DoResolve (ResolveContext rc) + public StringConstant (TypeSpec type, string s, Location loc) + : base (loc) { - type = TypeManager.string_type; + this.type = type; eclass = ExprClass.Value; - return this; + + Value = s; } public override object GetValue () @@ -1859,11 +1957,16 @@ namespace Mono.CSharp { // FIXME: Escape the string. return "\"" + Value + "\""; } + + public override long GetValueAsLong () + { + throw new NotSupportedException (); + } public override void Emit (EmitContext ec) { if (Value == null) { - ec.Emit (OpCodes.Ldnull); + ec.EmitNull (); return; } @@ -1871,13 +1974,14 @@ 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.CurrentType != TypeManager.string_type) { - if (TypeManager.string_empty == null) - TypeManager.string_empty = TypeManager.GetPredefinedField (TypeManager.string_type, "Empty", loc, TypeManager.string_type); - - if (TypeManager.string_empty != null) { - ec.Emit (OpCodes.Ldsfld, TypeManager.string_empty); - return; + if (Value.Length == 0 && ec.Module.Compiler.Settings.Optimize) { + var string_type = ec.BuiltinTypes.String; + if (ec.CurrentType != string_type) { + var m = ec.Module.PredefinedMembers.StringEmpty.Get (); + if (m != null) { + ec.Emit (OpCodes.Ldsfld, m); + return; + } } } @@ -1931,7 +2035,7 @@ namespace Mono.CSharp { public override Expression CreateExpressionTree (ResolveContext ec) { - if (type == InternalType.Null || type == TypeManager.object_type) { + if (type == InternalType.NullLiteral || type.BuiltinType == BuiltinTypeSpec.Type.Object) { // Optimized version, also avoids referencing literal internal type Arguments args = new Arguments (1); args.Add (new Argument (this)); @@ -1941,34 +2045,36 @@ namespace Mono.CSharp { return base.CreateExpressionTree (ec); } - protected override Expression DoResolve (ResolveContext ec) - { - 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 { + switch (targetType.BuiltinType) { + case BuiltinTypeSpec.Type.Object: + // Type it as string cast + enc.Encode (rc.Module.Compiler.BuiltinTypes.String); + goto case BuiltinTypeSpec.Type.String; + case BuiltinTypeSpec.Type.String: + case BuiltinTypeSpec.Type.Type: enc.Encode (byte.MaxValue); + return; + default: + var ac = targetType as ArrayContainer; + if (ac != null && ac.Rank == 1 && !ac.Element.IsArray) { + enc.Encode (uint.MaxValue); + return; + } + + break; } + + base.EncodeAttributeValue (rc, enc, targetType); } public override void Emit (EmitContext ec) { - ec.Emit (OpCodes.Ldnull); + ec.EmitNull (); // Only to make verifier happy - if (TypeManager.IsGenericParameter (type)) + if (type.IsGenericParameter) ec.Emit (OpCodes.Unbox_Any, type); } @@ -1982,28 +2088,28 @@ namespace Mono.CSharp { { if (targetType.IsPointer) { if (IsLiteral || this is NullPointer) - return new EmptyConstantCast (new NullPointer (loc), targetType); + return new NullPointer (targetType, loc); return null; } // Exlude internal compiler types - if (targetType.Kind == MemberKind.InternalCompilerType && targetType != InternalType.Dynamic && targetType != InternalType.Null) + if (targetType.Kind == MemberKind.InternalCompilerType && targetType.BuiltinType != BuiltinTypeSpec.Type.Dynamic) return null; if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType)) return null; - if (TypeManager.IsReferenceType (targetType)) + if (TypeSpec.IsReferenceType (targetType)) return new NullConstant (targetType, loc); - if (TypeManager.IsNullableType (targetType)) + if (targetType.IsNullableType) return Nullable.LiftedNull.Create (targetType, loc); return null; } - public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec targetType) + public override Constant ConvertImplicitly (TypeSpec targetType) { return ConvertExplicitly (false, targetType); } @@ -2023,6 +2129,11 @@ namespace Mono.CSharp { return GetSignatureForError (); } + public override long GetValueAsLong () + { + throw new NotSupportedException (); + } + public override bool IsDefaultValue { get { return true; } } @@ -2040,30 +2151,59 @@ namespace Mono.CSharp { } } + + // + // 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.EmitInt (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 class SideEffectConstant : Constant + { + 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; } - protected override Expression DoResolve (ResolveContext rc) - { - value = value.Resolve (rc); - - type = value.Type; - eclass = ExprClass.Value; - return this; + public override bool IsSideEffectFree { + get { + return false; + } } public override object GetValue () @@ -2076,6 +2216,11 @@ namespace Mono.CSharp { return value.GetValueAsLiteral (); } + public override long GetValueAsLong () + { + return value.GetValueAsLong (); + } + public override void Emit (EmitContext ec) { side_effect.EmitSideEffect (ec); @@ -2103,7 +2248,13 @@ namespace Mono.CSharp { 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; } } }