8582a4f8dfcd4facf87622c8242f002da9add880
[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 static readonly NullLiteral Null;
51
52                 static NullLiteral ()
53                 {
54                         Null = new NullLiteral ();
55                 }
56                         
57                 public NullLiteral ()
58                 {
59                         eclass = ExprClass.Value;
60                 }
61                 
62                 override public string AsString ()
63                 {
64                         return "null";
65                 }
66
67                 public override object GetValue ()
68                 {
69                         return null;
70                 }
71
72                 public override Expression DoResolve (EmitContext ec)
73                 {
74                         type = TypeManager.null_type;
75                         return this;
76                 }
77
78                 public override void Emit (EmitContext ec)
79                 {
80                         ec.ig.Emit (OpCodes.Ldnull);
81                 }
82
83                 public override Constant Increment ()
84                 {
85                         throw new NotSupportedException ();
86                 }
87
88                 public override bool IsDefaultValue {
89                         get {
90                                 return true;
91                         }
92                 }
93
94                 public override bool IsNegative {
95                         get {
96                                 return false;
97                         }
98                 }
99
100                 public override bool IsZeroInteger {
101                         get { return true; }
102                 }
103
104                 public override string GetSignatureForError()
105                 {
106                         return "null";
107                 }
108
109                 public override void Error_ValueCannotBeConverted (Location loc, Type t)
110                 {
111                         Report.Error (37, loc, "Cannot convert null to `{0}' because it is a value type",
112                                 TypeManager.CSharpName (t));
113                 }
114
115                 public override Constant ToType (Type type, Location loc)
116                 {
117                         if (!type.IsValueType && !TypeManager.IsEnumType (type))
118                                 return NullLiteral.Null;
119
120                         return base.ToType (type, loc);
121                 }
122
123         }
124
125         //
126         // A null literal in a pointer context
127         //
128         public class NullPointer : NullLiteral {
129                 public new static readonly NullLiteral Null;
130
131                 static NullPointer ()
132                 {
133                         Null = new NullPointer ();
134                 }
135
136                 private NullPointer ()
137                 {
138                         type = TypeManager.object_type;
139                 }
140
141                 public override void Emit (EmitContext ec)
142                 {
143                         ILGenerator ig = ec.ig;
144                                 
145                         ig.Emit (OpCodes.Ldc_I4_0);
146                         ig.Emit (OpCodes.Conv_U);
147                 }
148         }
149
150         public class BoolLiteral : BoolConstant {
151                 public BoolLiteral (bool val) : base (val)
152                 {
153                 }
154
155                 public override Expression DoResolve (EmitContext ec)
156                 {
157                         type = TypeManager.bool_type;
158                         return this;
159                 }
160         }
161
162         public class CharLiteral : CharConstant {
163                 public CharLiteral (char c) : base (c)
164                 {
165                 }
166
167                 public override Expression DoResolve (EmitContext ec)
168                 {
169                         type = TypeManager.char_type;
170                         return this;
171                 }
172         }
173
174         public class IntLiteral : IntConstant {
175                 public static IntLiteral One, Zero;
176                 
177                 static IntLiteral ()
178                 {
179                         Zero = new IntLiteral (0);
180                         One = new IntLiteral (1);
181                 }
182                 
183                 public IntLiteral (int l) : base (l)
184                 {
185                 }
186
187                 public override Expression DoResolve (EmitContext ec)
188                 {
189                         type = TypeManager.int32_type;
190                         return this;
191                 }
192         }
193
194         public class UIntLiteral : UIntConstant {
195                 public UIntLiteral (uint l) : base (l)
196                 {
197                 }
198
199                 public override Expression DoResolve (EmitContext ec)
200                 {
201                         type = TypeManager.uint32_type;
202                         return this;
203                 }
204         }
205         
206         public class LongLiteral : LongConstant {
207                 public LongLiteral (long l) : base (l)
208                 {
209                 }
210
211                 public override Expression DoResolve (EmitContext ec)
212                 {
213                         type = TypeManager.int64_type;
214
215                         return this;
216                 }
217         }
218
219         public class ULongLiteral : ULongConstant {
220                 public ULongLiteral (ulong l) : base (l)
221                 {
222                 }
223
224                 public override Expression DoResolve (EmitContext ec)
225                 {
226                         type = TypeManager.uint64_type;
227                         return this;
228                 }
229         }
230         
231         public class FloatLiteral : FloatConstant {
232                 
233                 public FloatLiteral (float f) : base (f)
234                 {
235                 }
236
237                 public override Expression DoResolve (EmitContext ec)
238                 {
239                         type = TypeManager.float_type;
240                         return this;
241                 }
242         }
243
244         public class DoubleLiteral : DoubleConstant {
245                 public DoubleLiteral (double d) : base (d)
246                 {
247                 }
248
249                 public override Expression DoResolve (EmitContext ec)
250                 {
251                         type = TypeManager.double_type;
252
253                         return this;
254                 }
255         }
256
257         public class DecimalLiteral : DecimalConstant {
258                 public DecimalLiteral (decimal d) : base (d)
259                 {
260                 }
261
262                 public override Expression DoResolve (EmitContext ec)
263                 {
264                         type = TypeManager.decimal_type;
265                         return this;
266                 }
267         }
268
269         public class StringLiteral : StringConstant {
270                 public StringLiteral (string s) : base (s)
271                 {
272                 }
273
274                 public override Expression DoResolve (EmitContext ec)
275                 {
276                         type = TypeManager.string_type;
277
278                         return this;
279                 }
280         }
281 }