X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fconstant.cs;h=ea7e7bfbf2e97b725c69a1da6fb78dd963287f8c;hb=a95479875edf8f6656039e50ae3cff82a2c666e0;hp=397d72c9a4ae7653be65733999a337aaf1567695;hpb=157cb97206f627685c15410953d2767146f6e426;p=mono.git diff --git a/mcs/mcs/constant.cs b/mcs/mcs/constant.cs index 397d72c9a4a..ea7e7bfbf2e 100644 --- a/mcs/mcs/constant.cs +++ b/mcs/mcs/constant.cs @@ -70,7 +70,7 @@ namespace Mono.CSharp { } } - public Constant ImplicitConversionRequired (ResolveContext ec, TypeSpec type, Location loc) + public Constant ImplicitConversionRequired (ResolveContext ec, TypeSpec type) { Constant c = ConvertImplicitly (type); if (c == null) @@ -89,7 +89,7 @@ namespace Mono.CSharp { if (this.type == type) return this; - if (!Convert.ImplicitNumericConversionExists (this.type, type)) + if (!Convert.ImplicitNumericConversionExists (this.type, type)) return null; bool fail; @@ -162,6 +162,88 @@ namespace Mono.CSharp { #endif } + // + // Returns a constant instance based on value and type. This is probing version of + // CreateConstantFromValue + // + public static Constant ExtractConstantFromValue (TypeSpec t, object v, Location loc) + { + switch (t.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + if (v is int) + return new IntConstant (t, (int) v, loc); + break; + case BuiltinTypeSpec.Type.String: + if (v is string) + return new StringConstant (t, (string) v, loc); + break; + case BuiltinTypeSpec.Type.UInt: + if (v is uint) + return new UIntConstant (t, (uint) v, loc); + break; + case BuiltinTypeSpec.Type.Long: + if (v is long) + return new LongConstant (t, (long) v, loc); + break; + case BuiltinTypeSpec.Type.ULong: + if (v is ulong) + return new ULongConstant (t, (ulong) v, loc); + break; + case BuiltinTypeSpec.Type.Float: + if (v is float) + return new FloatConstant (t, (float) v, loc); + break; + case BuiltinTypeSpec.Type.Double: + if (v is double) + return new DoubleConstant (t, (double) v, loc); + break; + case BuiltinTypeSpec.Type.Short: + if (v is short) + return new ShortConstant (t, (short) v, loc); + break; + case BuiltinTypeSpec.Type.UShort: + if (v is ushort) + return new UShortConstant (t, (ushort) v, loc); + break; + case BuiltinTypeSpec.Type.SByte: + if (v is sbyte) + return new SByteConstant (t, (sbyte) v, loc); + break; + case BuiltinTypeSpec.Type.Byte: + if (v is byte) + return new ByteConstant (t, (byte) v, loc); + break; + case BuiltinTypeSpec.Type.Char: + if (v is char) + return new CharConstant (t, (char) v, loc); + break; + case BuiltinTypeSpec.Type.Bool: + if (v is bool) + return new BoolConstant (t, (bool) v, loc); + break; + case BuiltinTypeSpec.Type.Decimal: + if (v is decimal) + return new DecimalConstant (t, (decimal) v, loc); + break; + } + + 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); + + if (TypeSpec.IsReferenceType (t)) + return new NullConstant (t, loc); + } + + return null; + } + + public override Expression CreateExpressionTree (ResolveContext ec) { Arguments args = new Arguments (2); @@ -440,7 +522,7 @@ namespace Mono.CSharp { return Value ? 1 : 0; } - public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType) { enc.Encode (Value); } @@ -491,7 +573,7 @@ namespace Mono.CSharp { Value = v; } - public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType) { enc.Encode (Value); } @@ -591,7 +673,7 @@ namespace Mono.CSharp { Value = v; } - public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType) { enc.Encode ((ushort) Value); } @@ -719,7 +801,7 @@ namespace Mono.CSharp { Value = v; } - public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType) { enc.Encode (Value); } @@ -822,7 +904,7 @@ namespace Mono.CSharp { Value = v; } - public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType) { enc.Encode (Value); } @@ -935,7 +1017,7 @@ namespace Mono.CSharp { Value = v; } - public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType) { enc.Encode (Value); } @@ -1044,7 +1126,7 @@ namespace Mono.CSharp { Value = v; } - public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType) { enc.Encode (Value); } @@ -1220,7 +1302,7 @@ namespace Mono.CSharp { Value = v; } - public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType) { enc.Encode (Value); } @@ -1337,7 +1419,7 @@ namespace Mono.CSharp { Value = v; } - public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType) { enc.Encode (Value); } @@ -1468,7 +1550,7 @@ namespace Mono.CSharp { Value = v; } - public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType) { enc.Encode (Value); } @@ -1564,23 +1646,35 @@ namespace Mono.CSharp { } public class FloatConstant : Constant { - public readonly float Value; + // + // Store constant value as double because float constant operations + // need to work on double value to match JIT + // + public readonly double DoubleValue; - public FloatConstant (BuiltinTypes types, float v, Location loc) + public FloatConstant (BuiltinTypes types, double v, Location loc) : this (types.Float, v, loc) { } - public FloatConstant (TypeSpec type, float v, Location loc) + public FloatConstant (TypeSpec type, double v, Location loc) : base (loc) { this.type = type; eclass = ExprClass.Value; - Value = v; + DoubleValue = v; } - public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + public override Constant ConvertImplicitly (TypeSpec type) + { + if (type.BuiltinType == BuiltinTypeSpec.Type.Double) + return new DoubleConstant (type, DoubleValue, loc); + + return base.ConvertImplicitly (type); + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType) { enc.Encode (Value); } @@ -1590,6 +1684,12 @@ namespace Mono.CSharp { ec.Emit (OpCodes.Ldc_R4, Value); } + public float Value { + get { + return (float) DoubleValue; + } + } + public override object GetValue () { return Value; @@ -1625,59 +1725,59 @@ namespace Mono.CSharp { if (Value < byte.MinValue || Value > byte.MaxValue || float.IsNaN (Value)) throw new OverflowException (); } - return new ByteConstant (target_type, (byte) Value, Location); + return new ByteConstant (target_type, (byte) DoubleValue, 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 (target_type, (sbyte) Value, Location); + return new SByteConstant (target_type, (sbyte) DoubleValue, 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 (target_type, (short) Value, Location); + return new ShortConstant (target_type, (short) DoubleValue, 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 (target_type, (ushort) Value, Location); + return new UShortConstant (target_type, (ushort) DoubleValue, 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 (target_type, (int) Value, Location); + return new IntConstant (target_type, (int) DoubleValue, 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 (target_type, (uint) Value, Location); + return new UIntConstant (target_type, (uint) DoubleValue, 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 (target_type, (long) Value, Location); + return new LongConstant (target_type, (long) DoubleValue, 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 (target_type, (ulong) Value, Location); + return new ULongConstant (target_type, (ulong) DoubleValue, Location); case BuiltinTypeSpec.Type.Double: - return new DoubleConstant (target_type, (double) Value, Location); + return new DoubleConstant (target_type, DoubleValue, 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 (target_type, (char) Value, Location); + return new CharConstant (target_type, (char) DoubleValue, Location); case BuiltinTypeSpec.Type.Decimal: - return new DecimalConstant (target_type, (decimal) Value, Location); + return new DecimalConstant (target_type, (decimal) DoubleValue, Location); } return null; @@ -1703,7 +1803,7 @@ namespace Mono.CSharp { Value = v; } - public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType) { enc.Encode (Value); } @@ -1931,8 +2031,6 @@ namespace Mono.CSharp { } public class StringConstant : Constant { - public readonly string Value; - public StringConstant (BuiltinTypes types, string s, Location loc) : this (types.String, s, loc) { @@ -1947,6 +2045,13 @@ namespace Mono.CSharp { Value = s; } + protected StringConstant (Location loc) + : base (loc) + { + } + + public string Value { get; protected set; } + public override object GetValue () { return Value; @@ -1988,7 +2093,7 @@ namespace Mono.CSharp { ec.Emit (OpCodes.Ldstr, Value); } - public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType) { // cast to object if (type != targetType) @@ -2019,6 +2124,121 @@ namespace Mono.CSharp { { return null; } + + public override Constant ConvertImplicitly (TypeSpec type) + { + if (IsDefaultValue && type.BuiltinType == BuiltinTypeSpec.Type.Object) + return new NullConstant (type, loc); + + return base.ConvertImplicitly (type); + } + } + + class NameOf : StringConstant + { + readonly SimpleName name; + + public NameOf (SimpleName name) + : base (name.Location) + { + this.name = name; + } + + protected override Expression DoResolve (ResolveContext rc) + { + throw new NotSupportedException (); + } + + bool ResolveArgumentExpression (ResolveContext rc, Expression expr) + { + var sn = expr as SimpleName; + if (sn != null) { + Value = sn.Name; + + if (rc.Module.Compiler.Settings.Version < LanguageVersion.V_6) + rc.Report.FeatureIsNotAvailable (rc.Module.Compiler, Location, "nameof operator"); + + if (sn.HasTypeArguments) { + // TODO: csc compatible but unhelpful error message + rc.Report.Error (1001, loc, "Identifier expected"); + return true; + } + + sn.LookupNameExpression (rc, MemberLookupRestrictions.IgnoreArity | MemberLookupRestrictions.IgnoreAmbiguity); + return true; + } + + var ma = expr as MemberAccess; + if (ma != null) { + FullNamedExpression fne = ma.LeftExpression as ATypeNameExpression; + if (fne == null) { + var qam = ma as QualifiedAliasMember; + if (qam == null) + return false; + + fne = qam.CreateExpressionFromAlias (rc); + if (fne == null) + return true; + } + + Value = ma.Name; + + if (rc.Module.Compiler.Settings.Version < LanguageVersion.V_6) + rc.Report.FeatureIsNotAvailable (rc.Module.Compiler, Location, "nameof operator"); + + if (ma.HasTypeArguments) { + // TODO: csc compatible but unhelpful error message + rc.Report.Error (1001, loc, "Identifier expected"); + return true; + } + + var left = fne.ResolveAsTypeOrNamespace (rc, true); + if (left == null) + return true; + + var ns = left as NamespaceExpression; + if (ns != null) { + FullNamedExpression retval = ns.LookupTypeOrNamespace (rc, ma.Name, 0, LookupMode.NameOf, loc); + if (retval == null) + ns.Error_NamespaceDoesNotExist (rc, ma.Name, 0); + + return true; + } + + if (left.Type.IsGenericOrParentIsGeneric && left.Type.GetDefinition () != left.Type) { + rc.Report.Error (8071, loc, "Type arguments are not allowed in the nameof operator"); + } + + var mexpr = MemberLookup (rc, false, left.Type, ma.Name, 0, MemberLookupRestrictions.IgnoreArity | MemberLookupRestrictions.IgnoreAmbiguity, loc); + if (mexpr == null) { + ma.Error_IdentifierNotFound (rc, left.Type); + return true; + } + + return true; + } + + return false; + } + + public Expression ResolveOverload (ResolveContext rc, Arguments args) + { + if (args == null || args.Count != 1) { + name.Error_NameDoesNotExist (rc); + return null; + } + + var arg = args [0]; + var res = ResolveArgumentExpression (rc, arg.Expr); + if (!res) { + name.Error_NameDoesNotExist (rc); + return null; + } + + type = rc.BuiltinTypes.String; + eclass = ExprClass.Value; + return this; + } } // @@ -2045,7 +2265,7 @@ namespace Mono.CSharp { return base.CreateExpressionTree (ec); } - public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType, TypeSpec parameterType) { switch (targetType.BuiltinType) { case BuiltinTypeSpec.Type.Object: @@ -2066,7 +2286,7 @@ namespace Mono.CSharp { break; } - base.EncodeAttributeValue (rc, enc, targetType); + base.EncodeAttributeValue (rc, enc, targetType, parameterType); } public override void Emit (EmitContext ec) @@ -2206,6 +2426,11 @@ namespace Mono.CSharp { } } + public override bool ContainsEmitWithAwait () + { + return side_effect.ContainsEmitWithAwait (); + } + public override object GetValue () { return value.GetValue (); @@ -2233,6 +2458,11 @@ namespace Mono.CSharp { value.EmitSideEffect (ec); } + public override void FlowAnalysis (FlowAnalysisContext fc) + { + side_effect.FlowAnalysis (fc); + } + public override bool IsDefaultValue { get { return value.IsDefaultValue; } }