Error message formating.
[mono.git] / mcs / mcs / literal.cs
1 //
2 // literal.cs: Literal representation for the IL tree.
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //   Marek Safar (marek.safar@seznam.cz)
7 //
8 // Copyright 2001 Ximian, Inc.
9 //
10 //
11 // Notice that during parsing we create objects of type Literal, but the
12 // types are not loaded (thats why the Resolve method has to assign the
13 // type at that point).
14 //
15 // Literals differ from the constants in that we know we encountered them
16 // as a literal in the source code (and some extra rules apply there) and
17 // they have to be resolved (since during parsing we have not loaded the
18 // types yet) while constants are created only after types have been loaded
19 // and are fully resolved when born.
20 //
21
22 using System;
23 using System.Reflection;
24 using System.Reflection.Emit;
25
26 namespace Mono.CSharp {
27
28         //
29         // The null literal
30         //
31         // Note: C# specification null-literal is NullLiteral of NullType type
32         //
33         public class NullLiteral : NullConstant
34         {
35                 //
36                 // Default type of null is an object
37                 //
38                 public NullLiteral (Location loc)
39                         : base (typeof (NullLiteral), loc)
40                 {
41                 }
42
43                 public override Expression CreateExpressionTree (ResolveContext ec)
44                 {
45                         // Optimized version, also avoids referencing literal internal type
46                         Arguments args = new Arguments (1);
47                         args.Add (new Argument (this));
48                         return CreateExpressionFactoryCall (ec, "Constant", args);
49                 }               
50
51                 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, Type t, bool expl)
52                 {
53                         if (TypeManager.IsGenericParameter (t)) {
54                                 ec.Report.Error(403, loc,
55                                         "Cannot convert null to the type parameter `{0}' because it could be a value " +
56                                         "type. Consider using `default ({0})' instead", t.Name);
57                                 return;
58                         }
59
60                         if (TypeManager.IsValueType (t)) {
61                                 ec.Report.Error(37, loc, "Cannot convert null to `{0}' because it is a value type",
62                                         TypeManager.CSharpName(t));
63                                 return;
64                         }
65
66                         base.Error_ValueCannotBeConverted (ec, loc, t, expl);
67                 }
68
69                 public override Constant ConvertImplicitly (ResolveContext rc, Type targetType)
70                 {
71                         //
72                         // Null literal is of object type
73                         //
74                         if (targetType == TypeManager.object_type)
75                                 return this;
76
77                         return base.ConvertImplicitly (rc, targetType);
78                 }
79
80                 public override bool IsLiteral {
81                         get { return true; }
82                 }
83
84 #if NET_4_0
85                 public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
86                 {
87                         return System.Linq.Expressions.Expression.Constant (null);
88                 }
89 #endif
90         }
91
92         //
93         // A null literal in a pointer context
94         //
95         class NullPointer : NullLiteral {
96                 public NullPointer (Location loc):
97                         base (loc)
98                 {
99                         type = TypeManager.object_type;
100                 }
101
102                 public override void Emit (EmitContext ec)
103                 {
104                         ILGenerator ig = ec.ig;
105                                 
106                         //
107                         // Emits null pointer
108                         //
109                         ig.Emit (OpCodes.Ldc_I4_0);
110                         ig.Emit (OpCodes.Conv_U);
111                 }
112         }
113
114         public class BoolLiteral : BoolConstant {
115                 public BoolLiteral (bool val, Location loc) : base (val, loc)
116                 {
117                 }
118
119                 public override bool IsLiteral {
120                         get { return true; }
121                 }
122         }
123
124         public class CharLiteral : CharConstant {
125                 public CharLiteral (char c, Location loc) : base (c, loc)
126                 {
127                 }
128
129                 public override bool IsLiteral {
130                         get { return true; }
131                 }
132         }
133
134         public class IntLiteral : IntConstant {
135                 public IntLiteral (int l, Location loc) : base (l, loc)
136                 {
137                 }
138
139                 public override Constant ConvertImplicitly (ResolveContext rc, Type type)
140                 {
141                         //
142                         // The 0 literal can be converted to an enum value
143                         //
144                         if (Value == 0 && TypeManager.IsEnumType (type)) {
145                                 Constant c = ConvertImplicitly (rc, TypeManager.GetEnumUnderlyingType (type));
146                                 if (c == null)
147                                         return null;
148
149                                 return new EnumConstant (c, type).Resolve (rc);
150                         }
151
152                         return base.ConvertImplicitly (rc, type);
153                 }
154
155                 public override bool IsLiteral {
156                         get { return true; }
157                 }
158         }
159
160         public class UIntLiteral : UIntConstant {
161                 public UIntLiteral (uint l, Location loc) : base (l, loc)
162                 {
163                 }
164
165                 public override bool IsLiteral {
166                         get { return true; }
167                 }
168         }
169         
170         public class LongLiteral : LongConstant {
171                 public LongLiteral (long l, Location loc) : base (l, loc)
172                 {
173                 }
174
175                 public override bool IsLiteral {
176                         get { return true; }
177                 }
178         }
179
180         public class ULongLiteral : ULongConstant {
181                 public ULongLiteral (ulong l, Location loc) : base (l, loc)
182                 {
183                 }
184
185                 public override bool IsLiteral {
186                         get { return true; }
187                 }
188         }
189         
190         public class FloatLiteral : FloatConstant {
191                 
192                 public FloatLiteral (float f, Location loc) : base (f, loc)
193                 {
194                 }
195
196                 public override bool IsLiteral {
197                         get { return true; }
198                 }
199
200         }
201
202         public class DoubleLiteral : DoubleConstant {
203                 public DoubleLiteral (double d, Location loc) : base (d, loc)
204                 {
205                 }
206
207                 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, Type target, bool expl)
208                 {
209                         if (target == TypeManager.float_type) {
210                                 Error_664 (ec, loc, "float", "f");
211                                 return;
212                         }
213
214                         if (target == TypeManager.decimal_type) {
215                                 Error_664 (ec, loc, "decimal", "m");
216                                 return;
217                         }
218
219                         base.Error_ValueCannotBeConverted (ec, loc, target, expl);
220                 }
221
222                 static void Error_664 (ResolveContext ec, Location loc, string type, string suffix)
223                 {
224                         ec.Report.Error (664, loc,
225                                 "Literal of type double cannot be implicitly converted to type `{0}'. Add suffix `{1}' to create a literal of this type",
226                                 type, suffix);
227                 }
228
229                 public override bool IsLiteral {
230                         get { return true; }
231                 }
232
233         }
234
235         public class DecimalLiteral : DecimalConstant {
236                 public DecimalLiteral (decimal d, Location loc) : base (d, loc)
237                 {
238                 }
239
240                 public override bool IsLiteral {
241                         get { return true; }
242                 }
243         }
244
245         public class StringLiteral : StringConstant {
246                 public StringLiteral (string s, Location loc) : base (s, loc)
247                 {
248                 }
249
250                 public override bool IsLiteral {
251                         get { return true; }
252                 }
253
254         }
255 }