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