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