2001-09-30 Miguel de Icaza <miguel@ximian.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 //
7 // (C) 2001 Ximian, Inc.
8 //
9
10 using System;
11 using System.Reflection;
12 using System.Reflection.Emit;
13
14 namespace CIR {
15         public abstract class Literal : Expression {
16                 // <summary>
17                 //   This is different from ToString in that ToString
18                 //   is supposed to be there for debugging purposes,
19                 //   and is not guarantee to be useful for anything else,
20                 //   AsString() will provide something that can be used
21                 //   for round-tripping C# code.  Maybe it can be used
22                 //   for IL assembly as well.
23                 // </summary>
24                 public abstract string AsString ();
25
26                 override public string ToString ()
27                 {
28                         return AsString ();
29                 }
30
31                 static public string descape (char c)
32                 {
33                         switch (c){
34                         case '\a':
35                                 return "\\a"; 
36                         case '\b':
37                                 return "\\b"; 
38                         case '\n':
39                                 return "\\n"; 
40                         case '\t':
41                                 return "\\t"; 
42                         case '\v':
43                                 return "\\v"; 
44                         case '\r':
45                                 return "\\r"; 
46                         case '\\':
47                                 return "\\\\";
48                         case '\f':
49                                 return "\\f"; 
50                         case '\0':
51                                 return "\\0"; 
52                         case '"':
53                                 return "\\\""; 
54                         case '\'':
55                                 return "\\\'"; 
56                         }
57                         return c.ToString ();
58                 }
59
60                 protected Literal ()
61                 {
62                         eclass = ExprClass.Value;
63                 }
64         }
65
66         public class NullLiteral : Literal {
67                 public NullLiteral ()
68                 {
69                 }
70                 
71                 override public string AsString ()
72                 {
73                         return "null";
74                 }
75
76                 public override Expression DoResolve (TypeContainer tc)
77                 {
78                         type = TypeManager.object_type;
79                         return this;
80                 }
81
82                 public override void Emit (EmitContext ec)
83                 {
84                         ec.ig.Emit (OpCodes.Ldnull);
85                 }
86         }
87
88         public class BoolLiteral : Literal {
89                 bool val;
90                 
91                 public BoolLiteral (bool val)
92                 {
93                         this.val = val;
94                 }
95
96                 override public string AsString ()
97                 {
98                         return val ? "true" : "false";
99                 }
100
101                 public override Expression DoResolve (TypeContainer tc)
102                 {
103                         type = TypeManager.bool_type;
104
105                         return this;
106                 }
107
108                 public override void Emit (EmitContext ec)
109                 {
110                         if (val)
111                                 ec.ig.Emit (OpCodes.Ldc_I4_1);
112                         else
113                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
114                 }
115         }
116
117         public class CharLiteral : Literal {
118                 char c;
119                 
120                 public CharLiteral (char c)
121                 {
122                         this.c = c;
123                 }
124
125                 override public string AsString ()
126                 {
127                         return "\"" + descape (c) + "\"";
128                 }
129
130                 public override Expression DoResolve (TypeContainer tc)
131                 {
132                         type = TypeManager.char_type;
133
134                         return this;
135                 }
136
137                 public override void Emit (EmitContext ec)
138                 {
139                         IntLiteral.EmitInt (ec.ig, c);
140                 }
141         }
142
143         public class IntLiteral : Literal {
144                 public readonly int Value;
145
146                 public IntLiteral (int l)
147                 {
148                         Value = l;
149                 }
150
151                 override public string AsString ()
152                 {
153                         return Value.ToString ();
154                 }
155
156                 public override Expression DoResolve (TypeContainer tc)
157                 {
158                         type = TypeManager.int32_type;
159
160                         return this;
161                 }
162
163                 public override void Emit (EmitContext ec)
164                 {
165                         ILGenerator ig = ec.ig;
166
167                         EmitInt (ig, Value);
168                 }
169
170                 static public void EmitInt (ILGenerator ig, int i)
171                 {
172                         switch (i){
173                         case -1:
174                                 ig.Emit (OpCodes.Ldc_I4_M1);
175                                 break;
176                                 
177                         case 0:
178                                 ig.Emit (OpCodes.Ldc_I4_0);
179                                 break;
180                                 
181                         case 1:
182                                 ig.Emit (OpCodes.Ldc_I4_1);
183                                 break;
184                                 
185                         case 2:
186                                 ig.Emit (OpCodes.Ldc_I4_2);
187                                 break;
188                                 
189                         case 3:
190                                 ig.Emit (OpCodes.Ldc_I4_3);
191                                 break;
192                                 
193                         case 4:
194                                 ig.Emit (OpCodes.Ldc_I4_4);
195                                 break;
196                                 
197                         case 5:
198                                 ig.Emit (OpCodes.Ldc_I4_5);
199                                 break;
200                                 
201                         case 6:
202                                 ig.Emit (OpCodes.Ldc_I4_6);
203                                 break;
204                                 
205                         case 7:
206                                 ig.Emit (OpCodes.Ldc_I4_7);
207                                 break;
208                                 
209                         case 8:
210                                 ig.Emit (OpCodes.Ldc_I4_8);
211                                 break;
212
213                         default:
214                                 if (i > 0 && i < 127){
215                                         ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
216                                 } else
217                                         ig.Emit (OpCodes.Ldc_I4, i);
218                                 break;
219                         }
220                 }
221         }
222
223         public class UIntLiteral : Literal {
224                 public readonly uint Value;
225
226                 public UIntLiteral (uint l)
227                 {
228                         Value = l;
229                 }
230
231                 override public string AsString ()
232                 {
233                         return Value.ToString ();
234                 }
235
236                 public override Expression DoResolve (TypeContainer tc)
237                 {
238                         type = TypeManager.uint32_type;
239
240                         return this;
241                 }
242
243                 public override void Emit (EmitContext ec)
244                 {
245                         ILGenerator ig = ec.ig;
246
247                         IntLiteral.EmitInt (ig, unchecked ((int) Value));
248                 }
249
250         }
251         
252         public class LongLiteral : Literal {
253                 public readonly long Value;
254
255                 public LongLiteral (long l)
256                 {
257                         Value = l;
258                 }
259
260                 override public string AsString ()
261                 {
262                         return Value.ToString ();
263                 }
264
265                 public override Expression DoResolve (TypeContainer tc)
266                 {
267                         type = TypeManager.int64_type;
268
269                         return this;
270                 }
271
272                 public override void Emit (EmitContext ec)
273                 {
274                         ILGenerator ig = ec.ig;
275
276                         EmitLong (ig, Value);
277                 }
278
279                 static public void EmitLong (ILGenerator ig, long l)
280                 {
281                         if (l >= -1 || l < Int32.MaxValue)
282                                 IntLiteral.EmitInt (ig, (int) l);
283                         else
284                                 ig.Emit (OpCodes.Ldc_I8, l);
285                 }
286         }
287
288         public class ULongLiteral : Literal {
289                 public readonly ulong Value;
290
291                 public ULongLiteral (ulong l)
292                 {
293                         Value = l;
294                 }
295
296                 override public string AsString ()
297                 {
298                         return Value.ToString ();
299                 }
300
301                 public override Expression DoResolve (TypeContainer tc)
302                 {
303                         type = TypeManager.uint64_type;
304
305                         return this;
306                 }
307
308                 public override void Emit (EmitContext ec)
309                 {
310                         ILGenerator ig = ec.ig;
311
312                         LongLiteral.EmitLong (ig, unchecked ((long) Value));
313                 }
314         }
315         
316         public class FloatLiteral : Literal {
317                 public readonly float Value;
318
319                 public FloatLiteral (float f)
320                 {
321                         Value = f;
322                 }
323
324                 override public string AsString ()
325                 {
326                         return Value.ToString ();
327                 }
328
329                 public override Expression DoResolve (TypeContainer tc)
330                 {
331                         type = TypeManager.float_type;
332
333                         return this;
334                 }
335
336                 public override void Emit (EmitContext ec)
337                 {
338                         ec.ig.Emit (OpCodes.Ldc_R4, Value);
339                 }
340         }
341
342         public class DoubleLiteral : Literal {
343                 public readonly double Value;
344
345                 public DoubleLiteral (double d)
346                 {
347                         Value = d;
348                 }
349
350                 override public string AsString ()
351                 {
352                         return Value.ToString ();
353                 }
354
355                 public override Expression DoResolve (TypeContainer tc)
356                 {
357                         type = TypeManager.double_type;
358
359                         return this;
360                 }
361
362                 public override void Emit (EmitContext ec)
363                 {
364                         ec.ig.Emit (OpCodes.Ldc_R8, Value);
365                 }
366         }
367
368         public class DecimalLiteral : Literal {
369                 public readonly decimal Value;
370
371                 public DecimalLiteral (decimal d)
372                 {
373                         Value = d;
374                 }
375
376                 override public string AsString ()
377                 {
378                         return Value.ToString ();
379                 }
380
381                 public override Expression DoResolve (TypeContainer tc)
382                 {
383                         type = TypeManager.decimal_type;
384
385                         return this;
386                 }
387
388                 public override void Emit (EmitContext ec)
389                 {
390                         throw new Exception ("Implement me");
391                 }
392         }
393
394         public class StringLiteral : Literal {
395                 string s;
396
397                 public StringLiteral (string s)
398                 {
399                         this.s = s;
400                 }
401
402                 // FIXME: Escape the string.
403                 override public string AsString ()
404                 {
405                         return "\"" + s + "\"";
406                 }
407
408                 public override Expression DoResolve (TypeContainer tc)
409                 {
410                         type = TypeManager.string_type;
411
412                         return this;
413                 }
414
415                 public override void Emit (EmitContext ec)
416                 {
417                         ec.ig.Emit (OpCodes.Ldstr, s);
418                 }
419         }
420 }