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