2010-05-27 Marek Safar <marek.safar@gmail.com>
[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 (InternalType.Null, 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, TypeSpec t, bool expl)
52                 {
53                         if (t.IsGenericParameter) {
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, TypeSpec 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                 public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
85                 {
86                         return System.Linq.Expressions.Expression.Constant (null);
87                 }
88         }
89
90         //
91         // A null literal in a pointer context
92         //
93         class NullPointer : NullLiteral {
94                 public NullPointer (Location loc):
95                         base (loc)
96                 {
97                         type = TypeManager.object_type;
98                 }
99
100                 public override void Emit (EmitContext ec)
101                 {
102                         //
103                         // Emits null pointer
104                         //
105                         ec.Emit (OpCodes.Ldc_I4_0);
106                         ec.Emit (OpCodes.Conv_U);
107                 }
108         }
109
110         public class BoolLiteral : BoolConstant {
111                 public BoolLiteral (bool val, Location loc) : base (val, loc)
112                 {
113                 }
114
115                 public override bool IsLiteral {
116                         get { return true; }
117                 }
118         }
119
120         public class CharLiteral : CharConstant {
121                 public CharLiteral (char c, Location loc) : base (c, loc)
122                 {
123                 }
124
125                 public override bool IsLiteral {
126                         get { return true; }
127                 }
128         }
129
130         public class IntLiteral : IntConstant {
131                 public IntLiteral (int l, Location loc) : base (l, loc)
132                 {
133                 }
134
135                 public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec type)
136                 {
137                         //
138                         // The 0 literal can be converted to an enum value
139                         //
140                         if (Value == 0 && TypeManager.IsEnumType (type)) {
141                                 Constant c = ConvertImplicitly (rc, EnumSpec.GetUnderlyingType (type));
142                                 if (c == null)
143                                         return null;
144
145                                 return new EnumConstant (c, type).Resolve (rc);
146                         }
147
148                         return base.ConvertImplicitly (rc, type);
149                 }
150
151                 public override bool IsLiteral {
152                         get { return true; }
153                 }
154         }
155
156         public class UIntLiteral : UIntConstant {
157                 public UIntLiteral (uint l, Location loc) : base (l, loc)
158                 {
159                 }
160
161                 public override bool IsLiteral {
162                         get { return true; }
163                 }
164         }
165         
166         public class LongLiteral : LongConstant {
167                 public LongLiteral (long l, Location loc) : base (l, loc)
168                 {
169                 }
170
171                 public override bool IsLiteral {
172                         get { return true; }
173                 }
174         }
175
176         public class ULongLiteral : ULongConstant {
177                 public ULongLiteral (ulong l, Location loc) : base (l, loc)
178                 {
179                 }
180
181                 public override bool IsLiteral {
182                         get { return true; }
183                 }
184         }
185         
186         public class FloatLiteral : FloatConstant {
187                 
188                 public FloatLiteral (float f, Location loc) : base (f, loc)
189                 {
190                 }
191
192                 public override bool IsLiteral {
193                         get { return true; }
194                 }
195
196         }
197
198         public class DoubleLiteral : DoubleConstant {
199                 public DoubleLiteral (double d, Location loc) : base (d, loc)
200                 {
201                 }
202
203                 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
204                 {
205                         if (target == TypeManager.float_type) {
206                                 Error_664 (ec, loc, "float", "f");
207                                 return;
208                         }
209
210                         if (target == TypeManager.decimal_type) {
211                                 Error_664 (ec, loc, "decimal", "m");
212                                 return;
213                         }
214
215                         base.Error_ValueCannotBeConverted (ec, loc, target, expl);
216                 }
217
218                 static void Error_664 (ResolveContext ec, Location loc, string type, string suffix)
219                 {
220                         ec.Report.Error (664, loc,
221                                 "Literal of type double cannot be implicitly converted to type `{0}'. Add suffix `{1}' to create a literal of this type",
222                                 type, suffix);
223                 }
224
225                 public override bool IsLiteral {
226                         get { return true; }
227                 }
228
229         }
230
231         public class DecimalLiteral : DecimalConstant {
232                 public DecimalLiteral (decimal d, Location loc) : base (d, loc)
233                 {
234                 }
235
236                 public override bool IsLiteral {
237                         get { return true; }
238                 }
239         }
240
241         public class StringLiteral : StringConstant {
242                 public StringLiteral (string s, Location loc) : base (s, loc)
243                 {
244                 }
245
246                 public override bool IsLiteral {
247                         get { return true; }
248                 }
249
250         }
251 }