//
// Author:
// Miguel de Icaza (miguel@ximian.com)
+// Marek Safar (marek.safar@seznam.cz)
//
// (C) 2001 Ximian, Inc.
//
+//
+// Notice that during parsing we create objects of type Literal, but the
+// types are not loaded (thats why the Resolve method has to assign the
+// type at that point).
+//
+// Literals differ from the constants in that we know we encountered them
+// as a literal in the source code (and some extra rules apply there) and
+// they have to be resolved (since during parsing we have not loaded the
+// types yet) while constants are created only after types have been loaded
+// and are fully resolved when born.
+//
using System;
using System.Reflection;
using System.Reflection.Emit;
+//
+// I put System.Null just so we do not have to special case it on
+// TypeManager.CSharpName
+//
+namespace System {
+ //
+ // Represents the Null Type, just used as a placeholder for the type in NullLiteral
+ //
+ public class Null {
+ }
+}
+
namespace Mono.CSharp {
- /// <summary>
- /// Base class for literals
- /// </summary>
- public abstract class Literal : Constant {
- static public string descape (char c)
- {
- switch (c){
- case '\a':
- return "\\a";
- case '\b':
- return "\\b";
- case '\n':
- return "\\n";
- case '\t':
- return "\\t";
- case '\v':
- return "\\v";
- case '\r':
- return "\\r";
- case '\\':
- return "\\\\";
- case '\f':
- return "\\f";
- case '\0':
- return "\\0";
- case '"':
- return "\\\"";
- case '\'':
- return "\\\'";
- }
- return c.ToString ();
- }
-
- protected Literal ()
- {
- }
+ //
+ // The NullType just exists to compare type equality, and for
+ // expressions that might have the `null type'
+ //
+ public class NullType {
}
- public class NullLiteral : Literal {
- public static readonly NullLiteral Null;
-
- static NullLiteral ()
- {
- Null = new NullLiteral ();
- }
-
- public NullLiteral ()
+
+ public class NullConstant : Constant
+ {
+ public NullConstant (Location loc):
+ base (loc)
{
- if (Null != null)
- throw new Exception ("More than one null has been created!");
+ eclass = ExprClass.Value;
+ type = TypeManager.null_type;
}
override public string AsString ()
return null;
}
- public override Expression DoResolve (EmitContext ec)
- {
- type = TypeManager.object_type;
- eclass = ExprClass.Value;
- return this;
- }
-
public override void Emit (EmitContext ec)
{
- ec.ig.Emit (OpCodes.Ldnull);
+ ec.ig.Emit(OpCodes.Ldnull);
}
- }
-
- public class BoolLiteral : Literal {
- public readonly bool Value;
- public BoolLiteral (bool val)
- {
- Value = val;
+ public override string ExprClassName {
+ get {
+ return GetSignatureForError ();
+ }
}
- override public string AsString ()
+ public override string GetSignatureForError ()
{
- return Value ? "true" : "false";
+ return "null";
}
- public override object GetValue ()
+ public override Constant Increment ()
{
- return (object) Value;
- }
-
-
- public override Expression DoResolve (EmitContext ec)
- {
- type = TypeManager.bool_type;
-
- return this;
+ throw new NotSupportedException ();
}
- public override void Emit (EmitContext ec)
+ public override bool IsDefaultValue
{
- if (Value)
- ec.ig.Emit (OpCodes.Ldc_I4_1);
- else
- ec.ig.Emit (OpCodes.Ldc_I4_0);
+ get { return true; }
}
- }
- public class CharLiteral : Literal {
- char c;
-
- public CharLiteral (char c)
+ public override bool IsNegative
{
- this.c = c;
+ get { return false; }
}
- override public string AsString ()
- {
- return "\"" + descape (c) + "\"";
+ public override bool IsNull {
+ get { return true; }
}
- public override object GetValue ()
+ public override bool IsZeroInteger
{
- return (object) c;
+ get { return true; }
}
-
- public override Expression DoResolve (EmitContext ec)
+
+ public override Constant ConvertExplicitly(bool inCheckedContext, Type target_type)
{
- type = TypeManager.char_type;
+ if (!TypeManager.IsValueType (target_type))
+ return new EmptyConstantCast (this, target_type);
- return this;
+ return null;
}
- public override void Emit (EmitContext ec)
+ public override Constant ConvertImplicitly (Type targetType)
{
- IntLiteral.EmitInt (ec.ig, c);
+ if (!TypeManager.IsValueType (targetType))
+ return new EmptyConstantCast (this, targetType);
+
+ return null;
}
}
- public class IntLiteral : Literal {
- public readonly int Value;
-
- public IntLiteral (int l)
+ //
+ // Represents default(X) when result can be reduced to null
+ //
+ public class NullDefault : EmptyConstantCast
+ {
+ public NullDefault(Constant value, Type type)
+ : base (value, type)
{
- Value = l;
}
- override public string AsString ()
+ public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl)
{
- return Value.ToString ();
+ base.Error_ValueCannotBeConverted (ec, loc, target, expl);
}
+ }
- public override object GetValue ()
+ //
+ // The null Literal constant
+ //
+ public class NullLiteral : NullConstant {
+ public NullLiteral (Location loc):
+ base (loc)
{
- return (object) Value;
}
public override Expression DoResolve (EmitContext ec)
{
- type = TypeManager.int32_type;
-
+ type = TypeManager.null_type;
return this;
}
- public override void Emit (EmitContext ec)
+ public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type t, bool expl)
{
- ILGenerator ig = ec.ig;
-
- EmitInt (ig, Value);
+ if (TypeManager.IsGenericParameter (t)) {
+ Report.Error(403, loc,
+ "Cannot convert null to the type parameter `{0}' because it could be a value " +
+ "type. Consider using `default ({0})' instead", t.Name);
+ } else {
+ Report.Error(37, loc, "Cannot convert null to `{0}' because it is a value type",
+ TypeManager.CSharpName(t));
+ }
}
- static public void EmitInt (ILGenerator ig, int i)
+ public override Constant ConvertImplicitly (Type targetType)
{
- switch (i){
- case -1:
- ig.Emit (OpCodes.Ldc_I4_M1);
- break;
-
- case 0:
- ig.Emit (OpCodes.Ldc_I4_0);
- break;
-
- case 1:
- ig.Emit (OpCodes.Ldc_I4_1);
- break;
-
- case 2:
- ig.Emit (OpCodes.Ldc_I4_2);
- break;
-
- case 3:
- ig.Emit (OpCodes.Ldc_I4_3);
- break;
-
- case 4:
- ig.Emit (OpCodes.Ldc_I4_4);
- break;
-
- case 5:
- ig.Emit (OpCodes.Ldc_I4_5);
- break;
-
- case 6:
- ig.Emit (OpCodes.Ldc_I4_6);
- break;
-
- case 7:
- ig.Emit (OpCodes.Ldc_I4_7);
- break;
-
- case 8:
- ig.Emit (OpCodes.Ldc_I4_8);
- break;
-
- default:
- if (i > 0 && i < 127){
- ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
- } else
- ig.Emit (OpCodes.Ldc_I4, i);
- break;
+ if (targetType.IsPointer)
+ return new EmptyConstantCast (NullPointer.Null, targetType);
+
+ if (TypeManager.IsGenericParameter(targetType)) {
+ GenericConstraints gc = null;
+
+#if GMCS_SOURCE
+ gc = TypeManager.GetTypeParameterConstraints(targetType);
+#endif
+ if (gc != null && gc.IsReferenceType)
+ return new EmptyConstantCast (this, targetType);
+
+ return null;
}
+
+ return base.ConvertImplicitly(targetType);
}
+
}
- public class UIntLiteral : Literal {
- public readonly uint Value;
+ //
+ // A null literal in a pointer context
+ //
+ public class NullPointer : NullLiteral {
+ public static readonly NullLiteral Null = new NullPointer ();
- public UIntLiteral (uint l)
+ private NullPointer ():
+ base (Location.Null)
{
- Value = l;
+ type = TypeManager.object_type;
}
- override public string AsString ()
+ public override void Emit (EmitContext ec)
{
- return Value.ToString ();
+ ILGenerator ig = ec.ig;
+
+ // TODO: why not use Ldnull instead ?
+ ig.Emit (OpCodes.Ldc_I4_0);
+ ig.Emit (OpCodes.Conv_U);
}
+ }
- public override object GetValue ()
+ public class BoolLiteral : BoolConstant {
+ public BoolLiteral (bool val, Location loc) : base (val, loc)
{
- return (object) Value;
}
-
+
public override Expression DoResolve (EmitContext ec)
{
- type = TypeManager.uint32_type;
-
+ type = TypeManager.bool_type;
return this;
}
-
- public override void Emit (EmitContext ec)
- {
- ILGenerator ig = ec.ig;
-
- IntLiteral.EmitInt (ig, unchecked ((int) Value));
- }
-
}
-
- public class LongLiteral : Literal {
- public readonly long Value;
- public LongLiteral (long l)
+ public class CharLiteral : CharConstant {
+ public CharLiteral (char c, Location loc) : base (c, loc)
{
- Value = l;
}
- override public string AsString ()
+ public override Expression DoResolve (EmitContext ec)
{
- return Value.ToString ();
+ type = TypeManager.char_type;
+ return this;
}
+ }
- public override object GetValue ()
+ public class IntLiteral : IntConstant {
+ public IntLiteral (int l, Location loc) : base (l, loc)
{
- return (object) Value;
}
-
+
public override Expression DoResolve (EmitContext ec)
{
- type = TypeManager.int64_type;
-
+ type = TypeManager.int32_type;
return this;
}
- public override void Emit (EmitContext ec)
+ public override Constant ConvertImplicitly (Type type)
{
- ILGenerator ig = ec.ig;
+ ///
+ /// The 0 literal can be converted to an enum value,
+ ///
+ if (Value == 0 && TypeManager.IsEnumType (type)) {
+ Constant c = ConvertImplicitly (TypeManager.EnumToUnderlying (type));
+ if (c == null)
+ return null;
- EmitLong (ig, Value);
+ return new EnumConstant (c, type);
+ }
+ return base.ConvertImplicitly (type);
}
- static public void EmitLong (ILGenerator ig, long l)
- {
- ig.Emit (OpCodes.Ldc_I8, l);
- }
}
- public class ULongLiteral : Literal {
- public readonly ulong Value;
-
- public ULongLiteral (ulong l)
+ public class UIntLiteral : UIntConstant {
+ public UIntLiteral (uint l, Location loc) : base (l, loc)
{
- Value = l;
}
- override public string AsString ()
+ public override Expression DoResolve (EmitContext ec)
{
- return Value.ToString ();
+ type = TypeManager.uint32_type;
+ return this;
}
-
- public override object GetValue ()
+ }
+
+ public class LongLiteral : LongConstant {
+ public LongLiteral (long l, Location loc) : base (l, loc)
{
- return (object) Value;
}
public override Expression DoResolve (EmitContext ec)
{
- type = TypeManager.uint64_type;
+ type = TypeManager.int64_type;
return this;
}
-
- public override void Emit (EmitContext ec)
- {
- ILGenerator ig = ec.ig;
-
- LongLiteral.EmitLong (ig, unchecked ((long) Value));
- }
}
-
- public class FloatLiteral : Literal {
- public readonly float Value;
- public FloatLiteral (float f)
+ public class ULongLiteral : ULongConstant {
+ public ULongLiteral (ulong l, Location loc) : base (l, loc)
{
- Value = f;
}
- override public string AsString ()
+ public override Expression DoResolve (EmitContext ec)
{
- return Value.ToString ();
+ type = TypeManager.uint64_type;
+ return this;
}
-
- public override object GetValue ()
+ }
+
+ public class FloatLiteral : FloatConstant {
+
+ public FloatLiteral (float f, Location loc) : base (f, loc)
{
- return (object) Value;
}
-
+
public override Expression DoResolve (EmitContext ec)
{
type = TypeManager.float_type;
-
return this;
}
-
- public override void Emit (EmitContext ec)
- {
- ec.ig.Emit (OpCodes.Ldc_R4, Value);
- }
}
- public class DoubleLiteral : Literal {
- public readonly double Value;
-
- public DoubleLiteral (double d)
+ public class DoubleLiteral : DoubleConstant {
+ public DoubleLiteral (double d, Location loc) : base (d, loc)
{
- Value = d;
}
- override public string AsString ()
- {
- return Value.ToString ();
- }
-
- public override object GetValue ()
- {
- return (object) Value;
- }
-
public override Expression DoResolve (EmitContext ec)
{
type = TypeManager.double_type;
return this;
}
- public override void Emit (EmitContext ec)
+ public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl)
{
- ec.ig.Emit (OpCodes.Ldc_R8, Value);
- }
- }
+ if (target == TypeManager.float_type) {
+ Error_664 (loc, "float", "f");
+ return;
+ }
- public class DecimalLiteral : Literal {
- public readonly decimal Value;
+ if (target == TypeManager.decimal_type) {
+ Error_664 (loc, "decimal", "m");
+ return;
+ }
- public DecimalLiteral (decimal d)
- {
- Value = d;
+ base.Error_ValueCannotBeConverted (ec, loc, target, expl);
}
- override public string AsString ()
+ static void Error_664 (Location loc, string type, string suffix)
{
- return Value.ToString ();
+ Report.Error (664, loc,
+ "Literal of type double cannot be implicitly converted to type `{0}'. Add suffix `{1}' to create a literal of this type",
+ type, suffix);
}
+ }
- public override object GetValue ()
+ public class DecimalLiteral : DecimalConstant {
+ public DecimalLiteral (decimal d, Location loc) : base (d, loc)
{
- return (object) Value;
}
public override Expression DoResolve (EmitContext ec)
{
type = TypeManager.decimal_type;
-
return this;
}
-
- public override void Emit (EmitContext ec)
- {
- throw new Exception ("Implement me");
- }
}
- public class StringLiteral : Literal {
- public readonly string Value;
-
- public StringLiteral (string s)
+ public class StringLiteral : StringConstant {
+ public StringLiteral (string s, Location loc) : base (s, loc)
{
- Value = s;
}
- // FIXME: Escape the string.
- override public string AsString ()
- {
- return "\"" + Value + "\"";
- }
-
- public override object GetValue ()
- {
- return (object) Value;
- }
-
public override Expression DoResolve (EmitContext ec)
{
type = TypeManager.string_type;
return this;
}
-
- public override void Emit (EmitContext ec)
- {
- ec.ig.Emit (OpCodes.Ldstr, Value);
- }
}
}