svn path=/branches/mono-1-1-9/mono/; revision=51217
[mono.git] / mcs / mcs / constant.cs
1 //
2 // constant.cs: Constants.
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.
8 //
9 //
10
11 namespace Mono.CSharp {
12
13         using System;
14         using System.Reflection.Emit;
15
16         /// <summary>
17         ///   Base class for constants and literals.
18         /// </summary>
19         public abstract class Constant : Expression {
20                 /// <remarks>
21                 ///   This is different from ToString in that ToString
22                 ///   is supposed to be there for debugging purposes,
23                 ///   and is not guaranteed to be useful for anything else,
24                 ///   AsString() will provide something that can be used
25                 ///   for round-tripping C# code.  Maybe it can be used
26                 ///   for IL assembly as well.
27                 /// </remarks>
28                 public abstract string AsString ();
29
30                 override public string ToString ()
31                 {
32                         return this.GetType ().Name + " (" + AsString () + ")";
33                 }
34
35                 /// <summary>
36                 ///  This is used to obtain the actual value of the literal
37                 ///  cast into an object.
38                 /// </summary>
39                 public abstract object GetValue ();
40
41                 public virtual object GetTypedValue ()
42                 {
43                         return GetValue ();
44                 }
45
46                 /// <summary>
47                 ///   Constants are always born in a fully resolved state
48                 /// </summary>
49                 public override Expression DoResolve (EmitContext ec)
50                 {
51                         return this;
52                 }
53
54                 public override void Error_ValueCannotBeConverted (Location loc, Type t)
55                 {
56                         // string is not real constant
57                         if (type == TypeManager.string_type)
58                                 base.Error_ValueCannotBeConverted (loc, t);
59                         else
60                                 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
61                                         AsString (), TypeManager.CSharpName (t));
62                 }
63
64
65                 //
66                 // The various ToXXXX conversion functions are used by the constant
67                 // folding evaluator.   A null value is returned if the conversion is
68                 // not possible.   
69                 //
70                 // Note: not all the patterns for catching `implicit_conv' are the same.
71                 // some implicit conversions can never be performed between two types
72                 // even if the conversion would be lossless (for example short to uint),
73                 // but some conversions are explicitly permitted by the standard provided
74                 // that there will be no loss of information (for example, int to uint).
75                 //
76                 public DoubleConstant ToDouble (Location loc)
77                 {
78                         DoubleConstant c = ConvertToDouble ();
79
80                         if (c == null)
81                                 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.double_type);
82
83                         return c;
84                 }
85
86                 public FloatConstant ToFloat (Location loc)
87                 {
88                         FloatConstant c = ConvertToFloat ();
89
90                         if (c == null)
91                                 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.float_type);
92
93                         return c;
94                 }
95
96                 public ULongConstant ToULong (Location loc)
97                 {
98                         ULongConstant c = ConvertToULong ();
99
100                         if (c == null)
101                                 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.uint64_type);
102
103                         return c;
104                 }
105
106                 public LongConstant ToLong (Location loc)
107                 {
108                         LongConstant c = ConvertToLong ();
109
110                         if (c == null)
111                                 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.int64_type);
112
113                         return c;
114                 }
115                 
116                 public UIntConstant ToUInt (Location loc)
117                 {
118                         UIntConstant c = ConvertToUInt ();
119
120                         if (c == null)
121                                 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.uint32_type);
122
123                         return c;
124                 }
125
126                 public IntConstant ToInt (Location loc)
127                 {
128                         IntConstant c = ConvertToInt ();
129
130                         if (c == null)
131                                 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.int32_type);
132
133                         return c;
134                 }
135
136                 public DecimalConstant ToDecimal (Location loc)
137                 {
138                         DecimalConstant c = ConvertToDecimal ();
139
140                         if (c == null)
141                                 Convert.Error_CannotConvertType (loc, Type, TypeManager.decimal_type);
142
143                         return c;
144                 }
145
146                 public virtual Constant ToType (Type type, Location loc)
147                 {
148                         if (Type == type)
149                                 return this;
150
151                         if (type == TypeManager.object_type)
152                                 return this;
153
154                         if (!Convert.ImplicitStandardConversionExists (Convert.ConstantEC, this, type)){
155                                 Error_ValueCannotBeConverted (loc, type);
156                                 return null;
157                         }
158
159                         // Special-case: The 0 literal can be converted to an enum value,
160                         // and ImplicitStandardConversionExists will return true in that case.
161                         if (IsZeroInteger && Type == TypeManager.int32_type && TypeManager.IsEnumType (type)) {
162                                 return new EnumConstant (this, type);
163                         }
164
165                         bool fail;                      
166                         object constant_value = TypeManager.ChangeType (GetValue (), type, out fail);
167                         if (fail){
168                                 Convert.Error_CannotImplicitConversion (loc, Type, type);
169                                 
170                                 //
171                                 // We should always catch the error before this is ever
172                                 // reached, by calling Convert.ImplicitStandardConversionExists
173                                 //
174                                 throw new Exception (
175                                         String.Format ("LookupConstantValue: This should never be reached {0} {1}", Type, type));
176                         }
177
178                         Constant retval;
179                         if (type == TypeManager.int32_type)
180                                 retval = new IntConstant ((int) constant_value);
181                         else if (type == TypeManager.uint32_type)
182                                 retval = new UIntConstant ((uint) constant_value);
183                         else if (type == TypeManager.int64_type)
184                                 retval = new LongConstant ((long) constant_value);
185                         else if (type == TypeManager.uint64_type)
186                                 retval = new ULongConstant ((ulong) constant_value);
187                         else if (type == TypeManager.float_type)
188                                 retval = new FloatConstant ((float) constant_value);
189                         else if (type == TypeManager.double_type)
190                                 retval = new DoubleConstant ((double) constant_value);
191                         else if (type == TypeManager.string_type)
192                                 retval = new StringConstant ((string) constant_value);
193                         else if (type == TypeManager.short_type)
194                                 retval = new ShortConstant ((short) constant_value);
195                         else if (type == TypeManager.ushort_type)
196                                 retval = new UShortConstant ((ushort) constant_value);
197                         else if (type == TypeManager.sbyte_type)
198                                 retval = new SByteConstant ((sbyte) constant_value);
199                         else if (type == TypeManager.byte_type)
200                                 retval = new ByteConstant ((byte) constant_value);
201                         else if (type == TypeManager.char_type)
202                                 retval = new CharConstant ((char) constant_value);
203                         else if (type == TypeManager.bool_type)
204                                 retval = new BoolConstant ((bool) constant_value);
205                         else if (type == TypeManager.decimal_type)
206                                 retval = new DecimalConstant ((decimal) constant_value);
207                         else
208                                 throw new Exception ("LookupConstantValue: Unhandled constant type: " + type);
209                         
210                         return retval;
211                 }
212
213                 public virtual DecimalConstant ConvertToDecimal ()
214                 {
215                         return null;
216                 }
217                 
218                 public virtual DoubleConstant ConvertToDouble ()
219                 {
220                         return null;
221                 }
222
223                 public virtual FloatConstant ConvertToFloat ()
224                 {
225                         return null;
226                 }
227
228                 public virtual ULongConstant ConvertToULong ()
229                 {
230                         return null;
231                 }
232
233                 public virtual LongConstant ConvertToLong ()
234                 {
235                         return null;
236                 }
237
238                 public virtual UIntConstant ConvertToUInt ()
239                 {
240                         return null;
241                 }
242
243                 public virtual IntConstant ConvertToInt ()
244                 {
245                         return null;
246                 }
247
248                 public abstract Constant Increment ();
249                 
250                 public abstract bool IsDefaultValue {
251                         get;
252                 }
253
254                 public abstract bool IsNegative {
255                         get;
256                 }
257
258                 //
259                 // Returns true iff 1) the stack type of this is one of Object, 
260                 // int32, int64 and 2) this == 0 or this == null.
261                 //
262                 public virtual bool IsZeroInteger {
263                         get { return false; }
264                 }
265         }
266         
267         public class BoolConstant : Constant {
268                 public readonly bool Value;
269                 
270                 public BoolConstant (bool val)
271                 {
272                         type = TypeManager.bool_type;
273                         eclass = ExprClass.Value;
274
275                         Value = val;
276                 }
277
278                 override public string AsString ()
279                 {
280                         return Value ? "true" : "false";
281                 }
282
283                 public override object GetValue ()
284                 {
285                         return (object) Value;
286                 }
287                                 
288                 
289                 public override void Emit (EmitContext ec)
290                 {
291                         if (Value)
292                                 ec.ig.Emit (OpCodes.Ldc_I4_1);
293                         else
294                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
295                 }
296
297                 public override Constant Increment ()
298                 {
299                         throw new NotSupportedException ();
300                 }
301         
302                 public override bool IsDefaultValue {
303                         get {
304                                 return !Value;
305                         }
306                 }
307
308                 public override bool IsNegative {
309                         get {
310                                 return false;
311                         }
312                 }
313         
314                 public override bool IsZeroInteger {
315                         get { return Value == false; }
316                 }
317         }
318
319         public class ByteConstant : Constant {
320                 public readonly byte Value;
321
322                 public ByteConstant (byte v)
323                 {
324                         type = TypeManager.byte_type;
325                         eclass = ExprClass.Value;
326                         Value = v;
327                 }
328
329                 public override void Emit (EmitContext ec)
330                 {
331                         IntLiteral.EmitInt (ec.ig, Value);
332                 }
333
334                 public override string AsString ()
335                 {
336                         return Value.ToString ();
337                 }
338
339                 public override object GetValue ()
340                 {
341                         return Value;
342                 }
343
344                 public override DoubleConstant ConvertToDouble ()
345                 {
346                         return new DoubleConstant (Value);
347                 }
348
349                 public override FloatConstant ConvertToFloat ()
350                 {
351                         return new FloatConstant (Value);
352                 }
353
354                 public override ULongConstant ConvertToULong ()
355                 {
356                         return new ULongConstant (Value);
357                 }
358
359                 public override LongConstant ConvertToLong ()
360                 {
361                         return new LongConstant (Value);
362                 }
363
364                 public override UIntConstant ConvertToUInt ()
365                 {
366                         return new UIntConstant (Value);
367                 }
368
369                 public override IntConstant ConvertToInt ()
370                 {
371                         return new IntConstant (Value);
372                 }
373
374                 public override Constant Increment ()
375                 {
376                         return new ByteConstant (checked ((byte)(Value + 1)));
377                 }
378
379                 public override bool IsDefaultValue {
380                         get {
381                                 return Value == 0;
382                         }
383                 }
384
385                 public override bool IsNegative {
386                         get {
387                                 return false;
388                         }
389                 }
390
391                 public override bool IsZeroInteger {
392                         get { return Value == 0; }
393                 }
394         }
395
396         public class CharConstant : Constant {
397                 public readonly char Value;
398
399                 public CharConstant (char v)
400                 {
401                         type = TypeManager.char_type;
402                         eclass = ExprClass.Value;
403                         Value = v;
404                 }
405
406                 public override void Emit (EmitContext ec)
407                 {
408                         IntLiteral.EmitInt (ec.ig, Value);
409                 }
410
411                 static public string descape (char c)
412                 {
413                         switch (c){
414                         case '\a':
415                                 return "\\a"; 
416                         case '\b':
417                                 return "\\b"; 
418                         case '\n':
419                                 return "\\n"; 
420                         case '\t':
421                                 return "\\t"; 
422                         case '\v':
423                                 return "\\v"; 
424                         case '\r':
425                                 return "\\r"; 
426                         case '\\':
427                                 return "\\\\";
428                         case '\f':
429                                 return "\\f"; 
430                         case '\0':
431                                 return "\\0"; 
432                         case '"':
433                                 return "\\\""; 
434                         case '\'':
435                                 return "\\\'"; 
436                         }
437                         return c.ToString ();
438                 }
439
440                 public override string AsString ()
441                 {
442                         return "\"" + descape (Value) + "\"";
443                 }
444
445                 public override object GetValue ()
446                 {
447                         return Value;
448                 }
449
450                 public override DoubleConstant ConvertToDouble ()
451                 {
452                         return new DoubleConstant (Value);
453                 }
454
455                 public override FloatConstant ConvertToFloat ()
456                 {
457                         return new FloatConstant (Value);
458                 }
459
460                 public override ULongConstant ConvertToULong ()
461                 {
462                         return new ULongConstant (Value);
463                 }
464
465                 public override LongConstant ConvertToLong ()
466                 {
467                         return new LongConstant (Value);
468                 }
469
470                 public override UIntConstant ConvertToUInt ()
471                 {
472                         return new UIntConstant (Value);
473                 }
474
475                 public override IntConstant ConvertToInt ()
476                 {
477                         return new IntConstant (Value);
478                 }
479
480                 public override Constant Increment ()
481                 {
482                         return new CharConstant (checked ((char)(Value + 1)));
483                 }
484                 
485                 public override bool IsDefaultValue {
486                         get {
487                                 return Value == 0;
488                         }
489                 }
490
491                 public override bool IsNegative {
492                         get {
493                                 return false;
494                         }
495                 }
496
497                 public override bool IsZeroInteger {
498                         get { return Value == '\0'; }
499                 }
500         }
501
502         public class SByteConstant : Constant {
503                 public readonly sbyte Value;
504
505                 public SByteConstant (sbyte v)
506                 {
507                         type = TypeManager.sbyte_type;
508                         eclass = ExprClass.Value;
509                         Value = v;
510                 }
511
512                 public override void Emit (EmitContext ec)
513                 {
514                         IntLiteral.EmitInt (ec.ig, Value);
515                 }
516
517                 public override string AsString ()
518                 {
519                         return Value.ToString ();
520                 }
521
522                 public override object GetValue ()
523                 {
524                         return Value;
525                 }
526
527                 public override DoubleConstant ConvertToDouble ()
528                 {
529                         return new DoubleConstant (Value);
530                 }
531
532                 public override FloatConstant ConvertToFloat ()
533                 {
534                         return new FloatConstant (Value);
535                 }
536
537                 public override ULongConstant ConvertToULong ()
538                 {
539                         if (Value >= 0)
540                                 return new ULongConstant ((ulong) Value);
541                         
542                         return null;
543                 }
544
545                 public override LongConstant ConvertToLong ()
546                 {
547                         return new LongConstant (Value);
548                 }
549
550                 public override UIntConstant ConvertToUInt ()
551                 {
552                         return null;
553                 }
554
555                 public override IntConstant ConvertToInt ()
556                 {
557                         return new IntConstant (Value);
558                 }
559
560                 public override Constant Increment ()
561                 {
562                     return new SByteConstant (checked((sbyte)(Value + 1)));
563                 }
564
565                 public override bool IsDefaultValue {
566                         get {
567                                 return Value == 0;
568                         }
569                 }
570
571                 public override bool IsNegative {
572                         get {
573                                 return Value < 0;
574                         }
575                 }
576                 
577                 public override bool IsZeroInteger {
578                         get { return Value == 0; }
579                 }
580         }
581
582         public class ShortConstant : Constant {
583                 public readonly short Value;
584
585                 public ShortConstant (short v)
586                 {
587                         type = TypeManager.short_type;
588                         eclass = ExprClass.Value;
589                         Value = v;
590                 }
591
592                 public override void Emit (EmitContext ec)
593                 {
594                         IntLiteral.EmitInt (ec.ig, Value);
595                 }
596
597                 public override string AsString ()
598                 {
599                         return Value.ToString ();
600                 }
601
602                 public override object GetValue ()
603                 {
604                         return Value;
605                 }
606
607                 public override DoubleConstant ConvertToDouble ()
608                 {
609                         return new DoubleConstant (Value);
610                 }
611
612                 public override FloatConstant ConvertToFloat ()
613                 {
614                         return new FloatConstant (Value);
615                 }
616
617                 public override ULongConstant ConvertToULong ()
618                 {
619                         return null;
620                 }
621
622                 public override LongConstant ConvertToLong ()
623                 {
624                         return new LongConstant (Value);
625                 }
626
627                 public override UIntConstant ConvertToUInt ()
628                 {
629                         return null;
630                 }
631
632                 public override IntConstant ConvertToInt ()
633                 {
634                         return new IntConstant (Value);
635                 }
636
637                 public override Constant Increment ()
638                 {
639                         return new ShortConstant (checked((short)(Value + 1)));
640                 }
641
642                 public override bool IsDefaultValue {
643                         get {
644                                 return Value == 0;
645                         }
646                 }
647                 
648                 public override bool IsZeroInteger {
649                         get { return Value == 0; }
650                 }
651
652                 public override bool IsNegative {
653                         get {
654                                 return Value < 0;
655                         }
656                 }
657         }
658
659         public class UShortConstant : Constant {
660                 public readonly ushort Value;
661
662                 public UShortConstant (ushort v)
663                 {
664                         type = TypeManager.ushort_type;
665                         eclass = ExprClass.Value;
666                         Value = v;
667                 }
668
669                 public override void Emit (EmitContext ec)
670                 {
671                         IntLiteral.EmitInt (ec.ig, Value);
672                 }
673
674                 public override string AsString ()
675                 {
676                         return Value.ToString ();
677                 }
678
679                 public override object GetValue ()
680                 {
681                         return Value;
682                 }
683
684                 public override DoubleConstant ConvertToDouble ()
685                 {
686                         return new DoubleConstant (Value);
687                 }
688
689                 public override FloatConstant ConvertToFloat ()
690                 {
691                         return new FloatConstant (Value);
692                 }
693
694                 public override ULongConstant ConvertToULong ()
695                 {
696                         return new ULongConstant (Value);
697                 }
698
699                 public override LongConstant ConvertToLong ()
700                 {
701                         return new LongConstant (Value);
702                 }
703
704                 public override UIntConstant ConvertToUInt ()
705                 {
706                         return new UIntConstant (Value);
707                 }
708
709                 public override IntConstant ConvertToInt ()
710                 {
711                         return new IntConstant (Value);
712                 }
713         
714                 public override Constant Increment ()
715                 {
716                         return new UShortConstant (checked((ushort)(Value + 1)));
717                 }
718
719                 public override bool IsDefaultValue {
720                         get {
721                                 return Value == 0;
722                         }
723                 }
724
725                 public override bool IsNegative {
726                         get {
727                                 return false;
728                         }
729                 }
730         
731                 public override bool IsZeroInteger {
732                         get { return Value == 0; }
733                 }
734         }
735
736         public class IntConstant : Constant {
737                 public readonly int Value;
738
739                 public IntConstant (int v)
740                 {
741                         type = TypeManager.int32_type;
742                         eclass = ExprClass.Value;
743                         Value = v;
744                 }
745
746                 static public void EmitInt (ILGenerator ig, int i)
747                 {
748                         switch (i){
749                         case -1:
750                                 ig.Emit (OpCodes.Ldc_I4_M1);
751                                 break;
752                                 
753                         case 0:
754                                 ig.Emit (OpCodes.Ldc_I4_0);
755                                 break;
756                                 
757                         case 1:
758                                 ig.Emit (OpCodes.Ldc_I4_1);
759                                 break;
760                                 
761                         case 2:
762                                 ig.Emit (OpCodes.Ldc_I4_2);
763                                 break;
764                                 
765                         case 3:
766                                 ig.Emit (OpCodes.Ldc_I4_3);
767                                 break;
768                                 
769                         case 4:
770                                 ig.Emit (OpCodes.Ldc_I4_4);
771                                 break;
772                                 
773                         case 5:
774                                 ig.Emit (OpCodes.Ldc_I4_5);
775                                 break;
776                                 
777                         case 6:
778                                 ig.Emit (OpCodes.Ldc_I4_6);
779                                 break;
780                                 
781                         case 7:
782                                 ig.Emit (OpCodes.Ldc_I4_7);
783                                 break;
784                                 
785                         case 8:
786                                 ig.Emit (OpCodes.Ldc_I4_8);
787                                 break;
788
789                         default:
790                                 if (i >= -128 && i <= 127){
791                                         ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
792                                 } else
793                                         ig.Emit (OpCodes.Ldc_I4, i);
794                                 break;
795                         }
796                 }
797
798                 public override void Emit (EmitContext ec)
799                 {
800                         EmitInt (ec.ig, Value);
801                 }
802
803                 public override string AsString ()
804                 {
805                         return Value.ToString ();
806                 }
807
808                 public override object GetValue ()
809                 {
810                         return Value;
811                 }
812
813                 public override DecimalConstant ConvertToDecimal()
814                 {
815                         return new DecimalConstant (Value);
816                 }
817
818                 public override DoubleConstant ConvertToDouble ()
819                 {
820                         return new DoubleConstant (Value);
821                 }
822
823                 public override FloatConstant ConvertToFloat ()
824                 {
825                         return new FloatConstant (Value);
826                 }
827
828                 public override ULongConstant ConvertToULong ()
829                 {
830                         if (Value < 0)
831                                 return null;
832
833                         return new ULongConstant ((ulong) Value);
834                 }
835
836                 public override LongConstant ConvertToLong ()
837                 {
838                         return new LongConstant (Value);
839                 }
840
841                 public override UIntConstant ConvertToUInt ()
842                 {
843                         if (Value < 0)
844                                 return null;
845
846                         return new UIntConstant ((uint) Value);
847                 }
848
849                 public override IntConstant ConvertToInt ()
850                 {
851                         return this;
852                 }
853
854                 public override Constant Increment ()
855                 {
856                         return new IntConstant (checked(Value + 1));
857                 }
858
859                 public override bool IsDefaultValue {
860                         get {
861                                 return Value == 0;
862                         }
863                 }
864                 
865                 public override bool IsNegative {
866                         get {
867                                 return Value < 0;
868                         }
869                 }
870
871                 public override bool IsZeroInteger {
872                         get { return Value == 0; }
873                 }
874         }
875
876         public class UIntConstant : Constant {
877                 public readonly uint Value;
878
879                 public UIntConstant (uint v)
880                 {
881                         type = TypeManager.uint32_type;
882                         eclass = ExprClass.Value;
883                         Value = v;
884                 }
885
886                 public override void Emit (EmitContext ec)
887                 {
888                         IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
889                 }
890
891                 public override string AsString ()
892                 {
893                         return Value.ToString ();
894                 }
895
896                 public override object GetValue ()
897                 {
898                         return Value;
899                 }
900
901                 public override DoubleConstant ConvertToDouble ()
902                 {
903                         return new DoubleConstant (Value);
904                 }
905
906                 public override FloatConstant ConvertToFloat ()
907                 {
908                         return new FloatConstant (Value);
909                 }
910
911                 public override ULongConstant ConvertToULong ()
912                 {
913                         return new ULongConstant (Value);
914                 }
915
916                 public override LongConstant ConvertToLong ()
917                 {
918                         return new LongConstant (Value);
919                 }
920
921                 public override UIntConstant ConvertToUInt ()
922                 {
923                         return this;
924                 }
925
926                 public override IntConstant ConvertToInt ()
927                 {
928                         return null;
929                 }
930         
931                 public override Constant Increment ()
932                 {
933                         return new UIntConstant (checked(Value + 1));
934                 }
935         
936                 public override bool IsDefaultValue {
937                         get {
938                                 return Value == 0;
939                         }
940                 }
941
942                 public override bool IsNegative {
943                         get {
944                                 return false;
945                         }
946                 }
947
948                 public override bool IsZeroInteger {
949                         get { return Value == 0; }
950                 }
951         }
952
953         public class LongConstant : Constant {
954                 public readonly long Value;
955
956                 public LongConstant (long v)
957                 {
958                         type = TypeManager.int64_type;
959                         eclass = ExprClass.Value;
960                         Value = v;
961                 }
962
963                 public override void Emit (EmitContext ec)
964                 {
965                         ILGenerator ig = ec.ig;
966
967                         EmitLong (ig, Value);
968                 }
969
970                 static public void EmitLong (ILGenerator ig, long l)
971                 {
972                         if ((l >> 32) == 0){
973                                 IntLiteral.EmitInt (ig, unchecked ((int) l));
974                                 ig.Emit (OpCodes.Conv_U8);
975                         } else {
976                                 ig.Emit (OpCodes.Ldc_I8, l);
977                         }
978                 }
979
980                 public override string AsString ()
981                 {
982                         return Value.ToString ();
983                 }
984
985                 public override object GetValue ()
986                 {
987                         return Value;
988                 }
989
990                 public override DoubleConstant ConvertToDouble ()
991                 {
992                         return new DoubleConstant (Value);
993                 }
994
995                 public override FloatConstant ConvertToFloat ()
996                 {
997                         return new FloatConstant (Value);
998                 }
999
1000                 public override ULongConstant ConvertToULong ()
1001                 {
1002                         if (Value < 0)
1003                                 return null;
1004                         
1005                         return new ULongConstant ((ulong) Value);
1006                 }
1007
1008                 public override LongConstant ConvertToLong ()
1009                 {
1010                         return this;
1011                 }
1012
1013                 public override UIntConstant ConvertToUInt ()
1014                 {
1015                         return null;
1016                 }
1017
1018                 public override IntConstant ConvertToInt ()
1019                 {
1020                         return null;
1021                 }
1022
1023                 public override Constant Increment ()
1024                 {
1025                         return new LongConstant (checked(Value + 1));
1026                 }
1027                 
1028                 public override bool IsDefaultValue {
1029                         get {
1030                                 return Value == 0;
1031                         }
1032                 }
1033
1034                 public override bool IsNegative {
1035                         get {
1036                                 return Value < 0;
1037                         }
1038                 }
1039
1040                 public override bool IsZeroInteger {
1041                         get { return Value == 0; }
1042                 }
1043         }
1044
1045         public class ULongConstant : Constant {
1046                 public readonly ulong Value;
1047
1048                 public ULongConstant (ulong v)
1049                 {
1050                         type = TypeManager.uint64_type;
1051                         eclass = ExprClass.Value;
1052                         Value = v;
1053                 }
1054
1055                 public override void Emit (EmitContext ec)
1056                 {
1057                         ILGenerator ig = ec.ig;
1058
1059                         LongLiteral.EmitLong (ig, unchecked ((long) Value));
1060                 }
1061
1062                 public override string AsString ()
1063                 {
1064                         return Value.ToString ();
1065                 }
1066
1067                 public override object GetValue ()
1068                 {
1069                         return Value;
1070                 }
1071
1072                 public override DoubleConstant ConvertToDouble ()
1073                 {
1074                         return new DoubleConstant (Value);
1075                 }
1076
1077                 public override FloatConstant ConvertToFloat ()
1078                 {
1079                         return new FloatConstant (Value);
1080                 }
1081
1082                 public override ULongConstant ConvertToULong ()
1083                 {
1084                         return this;
1085                 }
1086
1087                 public override LongConstant ConvertToLong ()
1088                 {
1089                         return null;
1090                 }
1091
1092                 public override UIntConstant ConvertToUInt ()
1093                 {
1094                         return null;
1095                 }
1096
1097                 public override IntConstant ConvertToInt ()
1098                 {
1099                         return null;
1100                 }
1101
1102                 public override Constant Increment ()
1103                 {
1104                         return new ULongConstant (checked(Value + 1));
1105                 }
1106
1107                 public override bool IsDefaultValue {
1108                         get {
1109                                 return Value == 0;
1110                         }
1111                 }
1112
1113                 public override bool IsNegative {
1114                         get {
1115                                 return false;
1116                         }
1117                 }
1118
1119                 public override bool IsZeroInteger {
1120                         get { return Value == 0; }
1121                 }
1122         }
1123
1124         public class FloatConstant : Constant {
1125                 public readonly float Value;
1126
1127                 public FloatConstant (float v)
1128                 {
1129                         type = TypeManager.float_type;
1130                         eclass = ExprClass.Value;
1131                         Value = v;
1132                 }
1133
1134                 public override void Emit (EmitContext ec)
1135                 {
1136                         ec.ig.Emit (OpCodes.Ldc_R4, Value);
1137                 }
1138
1139                 public override string AsString ()
1140                 {
1141                         return Value.ToString ();
1142                 }
1143
1144                 public override object GetValue ()
1145                 {
1146                         return Value;
1147                 }
1148
1149                 public override DoubleConstant ConvertToDouble ()
1150                 {
1151                         return new DoubleConstant (Value);
1152                 }
1153
1154                 public override FloatConstant ConvertToFloat ()
1155                 {
1156                         return this;
1157                 }
1158
1159                 public override LongConstant ConvertToLong ()
1160                 {
1161                         return null;
1162                 }
1163
1164                 public override UIntConstant ConvertToUInt ()
1165                 {
1166                         return null;
1167                 }
1168
1169                 public override IntConstant ConvertToInt ()
1170                 {
1171                         return null;
1172                 }
1173
1174                 public override Constant Increment ()
1175                 {
1176                         return new FloatConstant (checked(Value + 1));
1177                 }
1178
1179                 public override bool IsDefaultValue {
1180                         get {
1181                                 return Value == 0;
1182                         }
1183                 }
1184
1185                 public override bool IsNegative {
1186                         get {
1187                                 return Value < 0;
1188                         }
1189                 }
1190         }
1191
1192         public class DoubleConstant : Constant {
1193                 public readonly double Value;
1194
1195                 public DoubleConstant (double v)
1196                 {
1197                         type = TypeManager.double_type;
1198                         eclass = ExprClass.Value;
1199                         Value = v;
1200                 }
1201
1202                 public override void Emit (EmitContext ec)
1203                 {
1204                         ec.ig.Emit (OpCodes.Ldc_R8, Value);
1205                 }
1206
1207                 public override string AsString ()
1208                 {
1209                         return Value.ToString ();
1210                 }
1211
1212                 public override object GetValue ()
1213                 {
1214                         return Value;
1215                 }
1216
1217                 public override DoubleConstant ConvertToDouble ()
1218                 {
1219                         return this;
1220                 }
1221
1222                 public override FloatConstant ConvertToFloat ()
1223                 {
1224                         return null;
1225                 }
1226
1227                 public override ULongConstant ConvertToULong ()
1228                 {
1229                         return null;
1230                 }
1231
1232                 public override LongConstant ConvertToLong ()
1233                 {
1234                         return null;
1235                 }
1236
1237                 public override UIntConstant ConvertToUInt ()
1238                 {
1239                         return null;
1240                 }
1241
1242                 public override IntConstant ConvertToInt ()
1243                 {
1244                         return null;
1245                 }
1246
1247                 public override Constant Increment ()
1248                 {
1249                         return new DoubleConstant (checked(Value + 1));
1250                 }
1251
1252                 public override bool IsDefaultValue {
1253                         get {
1254                                 return Value == 0;
1255                         }
1256                 }
1257
1258                 public override bool IsNegative {
1259                         get {
1260                                 return Value < 0;
1261                         }
1262                 }
1263         }
1264
1265         public class DecimalConstant : Constant {
1266                 public readonly decimal Value;
1267
1268                 public DecimalConstant (decimal d)
1269                 {
1270                         type = TypeManager.decimal_type;
1271                         eclass = ExprClass.Value;
1272                         Value = d;
1273                 }
1274
1275                 override public string AsString ()
1276                 {
1277                         return Value.ToString ();
1278                 }
1279
1280                 public override object GetValue ()
1281                 {
1282                         return (object) Value;
1283                 }
1284
1285                 public override void Emit (EmitContext ec)
1286                 {
1287                         ILGenerator ig = ec.ig;
1288
1289                         int [] words = Decimal.GetBits (Value);
1290                         int power = (words [3] >> 16) & 0xff;
1291
1292                         if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
1293                         {
1294                                 IntConstant.EmitInt (ig, (int)Value);
1295                                 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1296                                 return;
1297                         }
1298
1299                         
1300                         //
1301                         // FIXME: we could optimize this, and call a better 
1302                         // constructor
1303                         //
1304
1305                         IntConstant.EmitInt (ig, words [0]);
1306                         IntConstant.EmitInt (ig, words [1]);
1307                         IntConstant.EmitInt (ig, words [2]);
1308
1309                         // sign
1310                         IntConstant.EmitInt (ig, words [3] >> 31);
1311
1312                         // power
1313                         IntConstant.EmitInt (ig, power);
1314
1315                         ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1316                 }
1317
1318                 public override Constant Increment ()
1319                 {
1320                         return new DecimalConstant (checked (Value + 1));
1321                 }
1322
1323                 public override bool IsDefaultValue {
1324                         get {
1325                                 return Value == 0;
1326                         }
1327                 }
1328
1329                 public override bool IsNegative {
1330                         get {
1331                                 return Value < 0;
1332                         }
1333                 }
1334         }
1335
1336         public class StringConstant : Constant {
1337                 public readonly string Value;
1338
1339                 public StringConstant (string s)
1340                 {
1341                         type = TypeManager.string_type;
1342                         eclass = ExprClass.Value;
1343                         Value = s;
1344                 }
1345
1346                 // FIXME: Escape the string.
1347                 override public string AsString ()
1348                 {
1349                         return "\"" + Value + "\"";
1350                 }
1351
1352                 public override object GetValue ()
1353                 {
1354                         return Value;
1355                 }
1356                 
1357                 public override void Emit (EmitContext ec)
1358                 {
1359                         if (Value == null)
1360                                 ec.ig.Emit (OpCodes.Ldnull);
1361                         else
1362                                 ec.ig.Emit (OpCodes.Ldstr, Value);
1363                 }
1364
1365                 public override Constant Increment ()
1366                 {
1367                         throw new NotSupportedException ();
1368                 }
1369
1370                 public override bool IsDefaultValue {
1371                         get {
1372                                 return Value == null;
1373                         }
1374                 }
1375
1376                 public override bool IsNegative {
1377                         get {
1378                                 return false;
1379                         }
1380                 }
1381         }
1382
1383 }
1384
1385