merge from trunk revisions 58933, 58935, 58936
[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 //
7 // (C) 2001 Ximian, Inc.
8 //
9 //
10 // Notice that during parsing we create objects of type Literal, but the
11 // types are not loaded (thats why the Resolve method has to assign the
12 // type at that point).
13 //
14 // Literals differ from the constants in that we know we encountered them
15 // as a literal in the source code (and some extra rules apply there) and
16 // they have to be resolved (since during parsing we have not loaded the
17 // types yet) while constants are created only after types have been loaded
18 // and are fully resolved when born.
19 //
20
21 using System;
22 using System.Reflection;
23 using System.Reflection.Emit;
24
25 //
26 // I put System.Null just so we do not have to special case it on 
27 // TypeManager.CSharpName
28 //
29 namespace System {
30         //
31         // Represents the Null Type, just used as a placeholder for the type in NullLiteral
32         //
33         public class Null {
34         }
35 }
36         
37 namespace Mono.CSharp {
38
39         //
40         // The NullType just exists to compare type equality, and for
41         // expressions that might have the `null type'
42         //
43         public class NullType {
44         }
45
46         //
47         // The null Literal constant
48         //
49         public class NullLiteral : Constant {
50                 public NullLiteral (Location loc):
51                         base (loc)
52                 {
53                         eclass = ExprClass.Value;
54                 }
55                 
56                 override public string AsString ()
57                 {
58                         return "null";
59                 }
60
61                 public override object GetValue ()
62                 {
63                         return null;
64                 }
65
66                 public override Expression DoResolve (EmitContext ec)
67                 {
68                         type = TypeManager.null_type;
69                         return this;
70                 }
71
72                 public override void Emit (EmitContext ec)
73                 {
74                         ec.ig.Emit (OpCodes.Ldnull);
75                 }
76
77                 public override Constant Increment ()
78                 {
79                         throw new NotSupportedException ();
80                 }
81
82                 public override bool IsDefaultValue {
83                         get {
84                                 return true;
85                         }
86                 }
87
88                 public override bool IsNegative {
89                         get {
90                                 return false;
91                         }
92                 }
93
94                 public override bool IsZeroInteger {
95                         get { return true; }
96                 }
97
98                 public override string GetSignatureForError()
99                 {
100                         return "null";
101                 }
102
103                 public override void Error_ValueCannotBeConverted (Location loc, Type t, bool expl)
104                 {
105                         Report.Error (37, loc, "Cannot convert null to `{0}' because it is a value type",
106                                 TypeManager.CSharpName (t));
107                 }
108
109                 public override Constant ToType (Type type, Location loc)
110                 {
111                         if (!type.IsValueType && !TypeManager.IsEnumType (type))
112                                 return this;
113
114                         return base.ToType (type, loc);
115                 }
116
117                 public override Constant Reduce(EmitContext ec, Type target_type)
118                 {
119                         if (!TypeManager.IsValueType (target_type))
120                                 return new NullCast (this, target_type);
121
122                         return null;
123                 }
124         }
125
126         //
127         // A null literal in a pointer context
128         //
129         public class NullPointer : NullLiteral {
130                 public static readonly NullLiteral Null;
131
132                 static NullPointer ()
133                 {
134                         Null = new NullPointer ();
135                 }
136
137                 private NullPointer ():
138                         base (Location.Null)
139                 {
140                         type = TypeManager.object_type;
141                 }
142
143                 public override void Emit (EmitContext ec)
144                 {
145                         ILGenerator ig = ec.ig;
146                                 
147                         ig.Emit (OpCodes.Ldc_I4_0);
148                         ig.Emit (OpCodes.Conv_U);
149                 }
150         }
151
152         public class BoolLiteral : BoolConstant {
153                 public BoolLiteral (bool val, Location loc) : base (val, loc)
154                 {
155                 }
156
157                 public override Expression DoResolve (EmitContext ec)
158                 {
159                         type = TypeManager.bool_type;
160                         return this;
161                 }
162         }
163
164         public class CharLiteral : CharConstant {
165                 public CharLiteral (char c, Location loc) : base (c, loc)
166                 {
167                 }
168
169                 public override Expression DoResolve (EmitContext ec)
170                 {
171                         type = TypeManager.char_type;
172                         return this;
173                 }
174         }
175
176         public class IntLiteral : IntConstant {
177                 public IntLiteral (int l, Location loc) : base (l, loc)
178                 {
179                 }
180
181                 public override Expression DoResolve (EmitContext ec)
182                 {
183                         type = TypeManager.int32_type;
184                         return this;
185                 }
186         }
187
188         public class UIntLiteral : UIntConstant {
189                 public UIntLiteral (uint l, Location loc) : base (l, loc)
190                 {
191                 }
192
193                 public override Expression DoResolve (EmitContext ec)
194                 {
195                         type = TypeManager.uint32_type;
196                         return this;
197                 }
198         }
199         
200         public class LongLiteral : LongConstant {
201                 public LongLiteral (long l, Location loc) : base (l, loc)
202                 {
203                 }
204
205                 public override Expression DoResolve (EmitContext ec)
206                 {
207                         type = TypeManager.int64_type;
208
209                         return this;
210                 }
211         }
212
213         public class ULongLiteral : ULongConstant {
214                 public ULongLiteral (ulong l, Location loc) : base (l, loc)
215                 {
216                 }
217
218                 public override Expression DoResolve (EmitContext ec)
219                 {
220                         type = TypeManager.uint64_type;
221                         return this;
222                 }
223         }
224         
225         public class FloatLiteral : FloatConstant {
226                 
227                 public FloatLiteral (float f, Location loc) : base (f, loc)
228                 {
229                 }
230
231                 public override Expression DoResolve (EmitContext ec)
232                 {
233                         type = TypeManager.float_type;
234                         return this;
235                 }
236         }
237
238         public class DoubleLiteral : DoubleConstant {
239                 public DoubleLiteral (double d, Location loc) : base (d, loc)
240                 {
241                 }
242
243                 public override Expression DoResolve (EmitContext ec)
244                 {
245                         type = TypeManager.double_type;
246
247                         return this;
248                 }
249         }
250
251         public class DecimalLiteral : DecimalConstant {
252                 public DecimalLiteral (decimal d, Location loc) : base (d, loc)
253                 {
254                 }
255
256                 public override Expression DoResolve (EmitContext ec)
257                 {
258                         type = TypeManager.decimal_type;
259                         return this;
260                 }
261         }
262
263         public class StringLiteral : StringConstant {
264                 public StringLiteral (string s, Location loc) : base (s, loc)
265                 {
266                 }
267
268                 public override Expression DoResolve (EmitContext ec)
269                 {
270                         type = TypeManager.string_type;
271
272                         return this;
273                 }
274         }
275 }