2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / bmcs / 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 IsNegative {
166                         get;
167                 }
168
169                 //
170                 // Returns true iff 1) the stack type of this is one of Object, 
171                 // int32, int64 and 2) this == 0 or this == null.
172                 //
173                 public virtual bool IsZeroInteger {
174                         get { return false; }
175                 }
176         }
177         
178         public class BoolConstant : Constant {
179                 public readonly bool Value;
180                 
181                 public BoolConstant (bool val)
182                 {
183                         type = TypeManager.bool_type;
184                         eclass = ExprClass.Value;
185
186                         Value = val;
187                 }
188
189                 override public string AsString ()
190                 {
191                         return Value ? "true" : "false";
192                 }
193
194                 public override object GetValue ()
195                 {
196                         return (object) Value;
197                 }
198                                 
199                 
200                 public override void Emit (EmitContext ec)
201                 {
202                         if (Value)
203                                 ec.ig.Emit (OpCodes.Ldc_I4_1);
204                         else
205                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
206                 }
207                 
208                 public override bool IsNegative {
209                         get {
210                                 return false;
211                         }
212                 }
213         
214                 public override bool IsZeroInteger {
215                         get { return Value == false; }
216                 }
217         }
218
219         public class ByteConstant : Constant {
220                 public readonly byte Value;
221
222                 public ByteConstant (byte v)
223                 {
224                         type = TypeManager.byte_type;
225                         eclass = ExprClass.Value;
226                         Value = v;
227                 }
228
229                 public override void Emit (EmitContext ec)
230                 {
231                         IntLiteral.EmitInt (ec.ig, Value);
232                 }
233
234                 public override string AsString ()
235                 {
236                         return Value.ToString ();
237                 }
238
239                 public override object GetValue ()
240                 {
241                         return Value;
242                 }
243
244                 public override DoubleConstant ConvertToDouble ()
245                 {
246                         return new DoubleConstant (Value);
247                 }
248
249                 public override FloatConstant ConvertToFloat ()
250                 {
251                         return new FloatConstant (Value);
252                 }
253
254                 public override ULongConstant ConvertToULong ()
255                 {
256                         return new ULongConstant (Value);
257                 }
258
259                 public override LongConstant ConvertToLong ()
260                 {
261                         return new LongConstant (Value);
262                 }
263
264                 public override UIntConstant ConvertToUInt ()
265                 {
266                         return new UIntConstant (Value);
267                 }
268
269                 public override IntConstant ConvertToInt ()
270                 {
271                         return new IntConstant (Value);
272                 }
273                 
274                 public override bool IsNegative {
275                         get {
276                                 return false;
277                         }
278                 }
279
280                 public override bool IsZeroInteger {
281                         get { return Value == 0; }
282                 }
283         }
284
285         public class CharConstant : Constant {
286                 public readonly char Value;
287
288                 public CharConstant (char v)
289                 {
290                         type = TypeManager.char_type;
291                         eclass = ExprClass.Value;
292                         Value = v;
293                 }
294
295                 public override void Emit (EmitContext ec)
296                 {
297                         IntLiteral.EmitInt (ec.ig, Value);
298                 }
299
300                 static public string descape (char c)
301                 {
302                         switch (c){
303                         case '\a':
304                                 return "\\a"; 
305                         case '\b':
306                                 return "\\b"; 
307                         case '\n':
308                                 return "\\n"; 
309                         case '\t':
310                                 return "\\t"; 
311                         case '\v':
312                                 return "\\v"; 
313                         case '\r':
314                                 return "\\r"; 
315                         case '\\':
316                                 return "\\\\";
317                         case '\f':
318                                 return "\\f"; 
319                         case '\0':
320                                 return "\\0"; 
321                         case '"':
322                                 return "\\\""; 
323                         case '\'':
324                                 return "\\\'"; 
325                         }
326                         return c.ToString ();
327                 }
328
329                 public override string AsString ()
330                 {
331                         return "\"" + descape (Value) + "\"";
332                 }
333
334                 public override object GetValue ()
335                 {
336                         return Value;
337                 }
338
339                 public override DoubleConstant ConvertToDouble ()
340                 {
341                         return new DoubleConstant (Value);
342                 }
343
344                 public override FloatConstant ConvertToFloat ()
345                 {
346                         return new FloatConstant (Value);
347                 }
348
349                 public override ULongConstant ConvertToULong ()
350                 {
351                         return new ULongConstant (Value);
352                 }
353
354                 public override LongConstant ConvertToLong ()
355                 {
356                         return new LongConstant (Value);
357                 }
358
359                 public override UIntConstant ConvertToUInt ()
360                 {
361                         return new UIntConstant (Value);
362                 }
363
364                 public override IntConstant ConvertToInt ()
365                 {
366                         return new IntConstant (Value);
367                 }
368                 
369                 public override bool IsNegative {
370                         get {
371                                 return false;
372                         }
373                 }
374
375                 public override bool IsZeroInteger {
376                         get { return Value == '\0'; }
377                 }
378         }
379
380         public class SByteConstant : Constant {
381                 public readonly sbyte Value;
382
383                 public SByteConstant (sbyte v)
384                 {
385                         type = TypeManager.sbyte_type;
386                         eclass = ExprClass.Value;
387                         Value = v;
388                 }
389
390                 public override void Emit (EmitContext ec)
391                 {
392                         IntLiteral.EmitInt (ec.ig, Value);
393                 }
394
395                 public override string AsString ()
396                 {
397                         return Value.ToString ();
398                 }
399
400                 public override object GetValue ()
401                 {
402                         return Value;
403                 }
404
405                 public override DoubleConstant ConvertToDouble ()
406                 {
407                         return new DoubleConstant (Value);
408                 }
409
410                 public override FloatConstant ConvertToFloat ()
411                 {
412                         return new FloatConstant (Value);
413                 }
414
415                 public override ULongConstant ConvertToULong ()
416                 {
417                         if (Value >= 0)
418                                 return new ULongConstant ((ulong) Value);
419                         
420                         return null;
421                 }
422
423                 public override LongConstant ConvertToLong ()
424                 {
425                         return new LongConstant (Value);
426                 }
427
428                 public override UIntConstant ConvertToUInt ()
429                 {
430                         return null;
431                 }
432
433                 public override IntConstant ConvertToInt ()
434                 {
435                         return new IntConstant (Value);
436                 }
437                 
438                 public override bool IsNegative {
439                         get {
440                                 return Value < 0;
441                         }
442                 }
443                 
444                 public override bool IsZeroInteger {
445                         get { return Value == 0; }
446                 }
447         }
448
449         public class ShortConstant : Constant {
450                 public readonly short Value;
451
452                 public ShortConstant (short v)
453                 {
454                         type = TypeManager.short_type;
455                         eclass = ExprClass.Value;
456                         Value = v;
457                 }
458
459                 public override void Emit (EmitContext ec)
460                 {
461                         IntLiteral.EmitInt (ec.ig, Value);
462                 }
463
464                 public override string AsString ()
465                 {
466                         return Value.ToString ();
467                 }
468
469                 public override object GetValue ()
470                 {
471                         return Value;
472                 }
473
474                 public override DoubleConstant ConvertToDouble ()
475                 {
476                         return new DoubleConstant (Value);
477                 }
478
479                 public override FloatConstant ConvertToFloat ()
480                 {
481                         return new FloatConstant (Value);
482                 }
483
484                 public override ULongConstant ConvertToULong ()
485                 {
486                         return null;
487                 }
488
489                 public override LongConstant ConvertToLong ()
490                 {
491                         return new LongConstant (Value);
492                 }
493
494                 public override UIntConstant ConvertToUInt ()
495                 {
496                         return null;
497                 }
498
499                 public override IntConstant ConvertToInt ()
500                 {
501                         return new IntConstant (Value);
502                 }
503                 
504                 public override bool IsZeroInteger {
505                         get { return Value == 0; }
506                 }
507
508                 public override bool IsNegative {
509                         get {
510                                 return Value < 0;
511                         }
512                 }
513         }
514
515         public class UShortConstant : Constant {
516                 public readonly ushort Value;
517
518                 public UShortConstant (ushort v)
519                 {
520                         type = TypeManager.ushort_type;
521                         eclass = ExprClass.Value;
522                         Value = v;
523                 }
524
525                 public override void Emit (EmitContext ec)
526                 {
527                         IntLiteral.EmitInt (ec.ig, Value);
528                 }
529
530                 public override string AsString ()
531                 {
532                         return Value.ToString ();
533                 }
534
535                 public override object GetValue ()
536                 {
537                         return Value;
538                 }
539
540                 public override DoubleConstant ConvertToDouble ()
541                 {
542                         return new DoubleConstant (Value);
543                 }
544
545                 public override FloatConstant ConvertToFloat ()
546                 {
547                         return new FloatConstant (Value);
548                 }
549
550                 public override ULongConstant ConvertToULong ()
551                 {
552                         return new ULongConstant (Value);
553                 }
554
555                 public override LongConstant ConvertToLong ()
556                 {
557                         return new LongConstant (Value);
558                 }
559
560                 public override UIntConstant ConvertToUInt ()
561                 {
562                         return new UIntConstant (Value);
563                 }
564
565                 public override IntConstant ConvertToInt ()
566                 {
567                         return new IntConstant (Value);
568                 }
569                 
570                 public override bool IsNegative {
571                         get {
572                                 return false;
573                         }
574                 }
575         
576                 public override bool IsZeroInteger {
577                         get { return Value == 0; }
578                 }
579         }
580
581         public class IntConstant : Constant {
582                 public readonly int Value;
583
584                 public IntConstant (int v)
585                 {
586                         type = TypeManager.int32_type;
587                         eclass = ExprClass.Value;
588                         Value = v;
589                 }
590
591                 static public void EmitInt (ILGenerator ig, int i)
592                 {
593                         switch (i){
594                         case -1:
595                                 ig.Emit (OpCodes.Ldc_I4_M1);
596                                 break;
597                                 
598                         case 0:
599                                 ig.Emit (OpCodes.Ldc_I4_0);
600                                 break;
601                                 
602                         case 1:
603                                 ig.Emit (OpCodes.Ldc_I4_1);
604                                 break;
605                                 
606                         case 2:
607                                 ig.Emit (OpCodes.Ldc_I4_2);
608                                 break;
609                                 
610                         case 3:
611                                 ig.Emit (OpCodes.Ldc_I4_3);
612                                 break;
613                                 
614                         case 4:
615                                 ig.Emit (OpCodes.Ldc_I4_4);
616                                 break;
617                                 
618                         case 5:
619                                 ig.Emit (OpCodes.Ldc_I4_5);
620                                 break;
621                                 
622                         case 6:
623                                 ig.Emit (OpCodes.Ldc_I4_6);
624                                 break;
625                                 
626                         case 7:
627                                 ig.Emit (OpCodes.Ldc_I4_7);
628                                 break;
629                                 
630                         case 8:
631                                 ig.Emit (OpCodes.Ldc_I4_8);
632                                 break;
633
634                         default:
635                                 if (i >= -128 && i <= 127){
636                                         ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
637                                 } else
638                                         ig.Emit (OpCodes.Ldc_I4, i);
639                                 break;
640                         }
641                 }
642
643                 public override void Emit (EmitContext ec)
644                 {
645                         EmitInt (ec.ig, Value);
646                 }
647
648                 public override string AsString ()
649                 {
650                         return Value.ToString ();
651                 }
652
653                 public override object GetValue ()
654                 {
655                         return Value;
656                 }
657
658                 public override DecimalConstant ConvertToDecimal()
659                 {
660                         return new DecimalConstant (Value);
661                 }
662
663                 public override DoubleConstant ConvertToDouble ()
664                 {
665                         return new DoubleConstant (Value);
666                 }
667
668                 public override FloatConstant ConvertToFloat ()
669                 {
670                         return new FloatConstant (Value);
671                 }
672
673                 public override ULongConstant ConvertToULong ()
674                 {
675                         if (Value < 0)
676                                 return null;
677
678                         return new ULongConstant ((ulong) Value);
679                 }
680
681                 public override LongConstant ConvertToLong ()
682                 {
683                         return new LongConstant (Value);
684                 }
685
686                 public override UIntConstant ConvertToUInt ()
687                 {
688                         if (Value < 0)
689                                 return null;
690
691                         return new UIntConstant ((uint) Value);
692                 }
693
694                 public override IntConstant ConvertToInt ()
695                 {
696                         return this;
697                 }
698                 
699                 public override bool IsNegative {
700                         get {
701                                 return Value < 0;
702                         }
703                 }
704
705                 public override bool IsZeroInteger {
706                         get { return Value == 0; }
707                 }
708         }
709
710         public class UIntConstant : Constant {
711                 public readonly uint Value;
712
713                 public UIntConstant (uint v)
714                 {
715                         type = TypeManager.uint32_type;
716                         eclass = ExprClass.Value;
717                         Value = v;
718                 }
719
720                 public override void Emit (EmitContext ec)
721                 {
722                         IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
723                 }
724
725                 public override string AsString ()
726                 {
727                         return Value.ToString ();
728                 }
729
730                 public override object GetValue ()
731                 {
732                         return Value;
733                 }
734
735                 public override DoubleConstant ConvertToDouble ()
736                 {
737                         return new DoubleConstant (Value);
738                 }
739
740                 public override FloatConstant ConvertToFloat ()
741                 {
742                         return new FloatConstant (Value);
743                 }
744
745                 public override ULongConstant ConvertToULong ()
746                 {
747                         return new ULongConstant (Value);
748                 }
749
750                 public override LongConstant ConvertToLong ()
751                 {
752                         return new LongConstant (Value);
753                 }
754
755                 public override UIntConstant ConvertToUInt ()
756                 {
757                         return this;
758                 }
759
760                 public override IntConstant ConvertToInt ()
761                 {
762                         return null;
763                 }
764                 
765                 public override bool IsNegative {
766                         get {
767                                 return false;
768                         }
769                 }
770
771                 public override bool IsZeroInteger {
772                         get { return Value == 0; }
773                 }
774         }
775
776         public class LongConstant : Constant {
777                 public readonly long Value;
778
779                 public LongConstant (long v)
780                 {
781                         type = TypeManager.int64_type;
782                         eclass = ExprClass.Value;
783                         Value = v;
784                 }
785
786                 public override void Emit (EmitContext ec)
787                 {
788                         ILGenerator ig = ec.ig;
789
790                         EmitLong (ig, Value);
791                 }
792
793                 static public void EmitLong (ILGenerator ig, long l)
794                 {
795                         if ((l >> 32) == 0){
796                                 IntLiteral.EmitInt (ig, unchecked ((int) l));
797                                 ig.Emit (OpCodes.Conv_U8);
798                         } else {
799                                 ig.Emit (OpCodes.Ldc_I8, l);
800                         }
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 DoubleConstant ConvertToDouble ()
814                 {
815                         return new DoubleConstant (Value);
816                 }
817
818                 public override FloatConstant ConvertToFloat ()
819                 {
820                         return new FloatConstant (Value);
821                 }
822
823                 public override ULongConstant ConvertToULong ()
824                 {
825                         if (Value < 0)
826                                 return null;
827                         
828                         return new ULongConstant ((ulong) Value);
829                 }
830
831                 public override LongConstant ConvertToLong ()
832                 {
833                         return this;
834                 }
835
836                 public override UIntConstant ConvertToUInt ()
837                 {
838                         return null;
839                 }
840
841                 public override IntConstant ConvertToInt ()
842                 {
843                         return null;
844                 }
845                 
846                 public override bool IsNegative {
847                         get {
848                                 return Value < 0;
849                         }
850                 }
851
852                 public override bool IsZeroInteger {
853                         get { return Value == 0; }
854                 }
855         }
856
857         public class ULongConstant : Constant {
858                 public readonly ulong Value;
859
860                 public ULongConstant (ulong v)
861                 {
862                         type = TypeManager.uint64_type;
863                         eclass = ExprClass.Value;
864                         Value = v;
865                 }
866
867                 public override void Emit (EmitContext ec)
868                 {
869                         ILGenerator ig = ec.ig;
870
871                         LongLiteral.EmitLong (ig, unchecked ((long) Value));
872                 }
873
874                 public override string AsString ()
875                 {
876                         return Value.ToString ();
877                 }
878
879                 public override object GetValue ()
880                 {
881                         return Value;
882                 }
883
884                 public override DoubleConstant ConvertToDouble ()
885                 {
886                         return new DoubleConstant (Value);
887                 }
888
889                 public override FloatConstant ConvertToFloat ()
890                 {
891                         return new FloatConstant (Value);
892                 }
893
894                 public override ULongConstant ConvertToULong ()
895                 {
896                         return this;
897                 }
898
899                 public override LongConstant ConvertToLong ()
900                 {
901                         return null;
902                 }
903
904                 public override UIntConstant ConvertToUInt ()
905                 {
906                         return null;
907                 }
908
909                 public override IntConstant ConvertToInt ()
910                 {
911                         return null;
912                 }
913                 
914                 public override bool IsNegative {
915                         get {
916                                 return false;
917                         }
918                 }
919
920                 public override bool IsZeroInteger {
921                         get { return Value == 0; }
922                 }
923         }
924
925         public class FloatConstant : Constant {
926                 public readonly float Value;
927
928                 public FloatConstant (float v)
929                 {
930                         type = TypeManager.float_type;
931                         eclass = ExprClass.Value;
932                         Value = v;
933                 }
934
935                 public override void Emit (EmitContext ec)
936                 {
937                         ec.ig.Emit (OpCodes.Ldc_R4, Value);
938                 }
939
940                 public override string AsString ()
941                 {
942                         return Value.ToString ();
943                 }
944
945                 public override object GetValue ()
946                 {
947                         return Value;
948                 }
949
950                 public override DoubleConstant ConvertToDouble ()
951                 {
952                         return new DoubleConstant (Value);
953                 }
954
955                 public override FloatConstant ConvertToFloat ()
956                 {
957                         return this;
958                 }
959
960                 public override LongConstant ConvertToLong ()
961                 {
962                         return null;
963                 }
964
965                 public override UIntConstant ConvertToUInt ()
966                 {
967                         return null;
968                 }
969
970                 public override IntConstant ConvertToInt ()
971                 {
972                         return null;
973                 }
974
975                 public override bool IsNegative {
976                         get {
977                                 return Value < 0;
978                         }
979                 }
980         }
981
982         public class DoubleConstant : Constant {
983                 public readonly double Value;
984
985                 public DoubleConstant (double v)
986                 {
987                         type = TypeManager.double_type;
988                         eclass = ExprClass.Value;
989                         Value = v;
990                 }
991
992                 public override void Emit (EmitContext ec)
993                 {
994                         ec.ig.Emit (OpCodes.Ldc_R8, Value);
995                 }
996
997                 public override string AsString ()
998                 {
999                         return Value.ToString ();
1000                 }
1001
1002                 public override object GetValue ()
1003                 {
1004                         return Value;
1005                 }
1006
1007                 public override DoubleConstant ConvertToDouble ()
1008                 {
1009                         return this;
1010                 }
1011
1012                 public override FloatConstant ConvertToFloat ()
1013                 {
1014                         return null;
1015                 }
1016
1017                 public override ULongConstant ConvertToULong ()
1018                 {
1019                         return null;
1020                 }
1021
1022                 public override LongConstant ConvertToLong ()
1023                 {
1024                         return null;
1025                 }
1026
1027                 public override UIntConstant ConvertToUInt ()
1028                 {
1029                         return null;
1030                 }
1031
1032                 public override IntConstant ConvertToInt ()
1033                 {
1034                         return null;
1035                 }
1036
1037                 public override bool IsNegative {
1038                         get {
1039                                 return Value < 0;
1040                         }
1041                 }
1042         }
1043
1044         public class DecimalConstant : Constant {
1045                 public readonly decimal Value;
1046
1047                 public DecimalConstant (decimal d)
1048                 {
1049                         type = TypeManager.decimal_type;
1050                         eclass = ExprClass.Value;
1051                         Value = d;
1052                 }
1053
1054                 override public string AsString ()
1055                 {
1056                         return Value.ToString ();
1057                 }
1058
1059                 public override object GetValue ()
1060                 {
1061                         return (object) Value;
1062                 }
1063
1064                 public override void Emit (EmitContext ec)
1065                 {
1066                         ILGenerator ig = ec.ig;
1067
1068                         int [] words = Decimal.GetBits (Value);
1069                         int power = (words [3] >> 16) & 0xff;
1070
1071                         if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
1072                         {
1073                                 IntConstant.EmitInt (ig, (int)Value);
1074                                 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1075                                 return;
1076                         }
1077
1078                         
1079                         //
1080                         // FIXME: we could optimize this, and call a better 
1081                         // constructor
1082                         //
1083
1084                         IntConstant.EmitInt (ig, words [0]);
1085                         IntConstant.EmitInt (ig, words [1]);
1086                         IntConstant.EmitInt (ig, words [2]);
1087
1088                         // sign
1089                         IntConstant.EmitInt (ig, words [3] >> 31);
1090
1091                         // power
1092                         IntConstant.EmitInt (ig, power);
1093
1094                         ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1095                 }
1096
1097                 public override bool IsNegative {
1098                         get {
1099                                 return Value < 0;
1100                         }
1101                 }
1102         }
1103
1104         public class StringConstant : Constant {
1105                 public readonly string Value;
1106
1107                 public StringConstant (string s)
1108                 {
1109                         type = TypeManager.string_type;
1110                         eclass = ExprClass.Value;
1111                         Value = s;
1112                 }
1113
1114                 // FIXME: Escape the string.
1115                 override public string AsString ()
1116                 {
1117                         return "\"" + Value + "\"";
1118                 }
1119
1120                 public override object GetValue ()
1121                 {
1122                         return Value;
1123                 }
1124                 
1125                 public override void Emit (EmitContext ec)
1126                 {
1127                         if (Value == null)
1128                                 ec.ig.Emit (OpCodes.Ldnull);
1129                         else
1130                                 ec.ig.Emit (OpCodes.Ldstr, Value);
1131                 }
1132
1133                 public override bool IsNegative {
1134                         get {
1135                                 return false;
1136                         }
1137                 }
1138         }
1139
1140 }
1141
1142