This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[mono.git] / mcs / mcs / constant.cs
1 //
2 // constant.cs: Constants.
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.
8 //
9 //
10
11 namespace Mono.CSharp {
12
13         using System;
14         using System.Reflection.Emit;
15
16         /// <summary>
17         ///   Base class for constants and literals.
18         /// </summary>
19         public abstract class Constant : Expression {
20                 /// <remarks>
21                 ///   This is different from ToString in that ToString
22                 ///   is supposed to be there for debugging purposes,
23                 ///   and is not guaranteed to be useful for anything else,
24                 ///   AsString() will provide something that can be used
25                 ///   for round-tripping C# code.  Maybe it can be used
26                 ///   for IL assembly as well.
27                 /// </remarks>
28                 public abstract string AsString ();
29
30                 override public string ToString ()
31                 {
32                         return this.GetType ().Name + " (" + AsString () + ")";
33                 }
34
35                 /// <summary>
36                 ///  This is used to obtain the actual value of the literal
37                 ///  cast into an object.
38                 /// </summary>
39                 public abstract object GetValue ();
40
41                 /// <summary>
42                 ///   Constants are always born in a fully resolved state
43                 /// </summary>
44                 public override Expression DoResolve (EmitContext ec)
45                 {
46                         return this;
47                 }
48
49                 //
50                 // The various ToXXXX conversion functions are used by the constant
51                 // folding evaluator.   A null value is returned if the conversion is
52                 // not possible.   
53                 //
54                 // Note: not all the patterns for catching `implicit_conv' are the same.
55                 // some implicit conversions can never be performed between two types
56                 // even if the conversion would be lossless (for example short to uint),
57                 // but some conversions are explicitly permitted by the standard provided
58                 // that there will be no loss of information (for example, int to uint).
59                 //
60                 public DoubleConstant ToDouble (Location loc)
61                 {
62                         DoubleConstant c = ConvertToDouble ();
63
64                         if (c == null)
65                                 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.double_type);
66
67                         return c;
68                 }
69
70                 public FloatConstant ToFloat (Location loc)
71                 {
72                         FloatConstant c = ConvertToFloat ();
73
74                         if (c == null)
75                                 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.float_type);
76
77                         return c;
78                 }
79
80                 public ULongConstant ToULong (Location loc)
81                 {
82                         ULongConstant c = ConvertToULong ();
83
84                         if (c == null)
85                                 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.uint64_type);
86
87                         return c;
88                 }
89
90                 public LongConstant ToLong (Location loc)
91                 {
92                         LongConstant c = ConvertToLong ();
93
94                         if (c == null)
95                                 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.int64_type);
96
97                         return c;
98                 }
99                 
100                 public UIntConstant ToUInt (Location loc)
101                 {
102                         UIntConstant c = ConvertToUInt ();
103
104                         if (c == null)
105                                 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.uint32_type);
106
107                         return c;
108                 }
109
110                 public IntConstant ToInt (Location loc)
111                 {
112                         IntConstant c = ConvertToInt ();
113
114                         if (c == null)
115                                 Convert.Error_CannotImplicitConversion (loc, Type, TypeManager.int32_type);
116
117                         return c;
118                 }
119                 
120                 public 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                 //
151                 // Returns true iff 1) the stack type of this is one of Object, 
152                 // int32, int64 and 2) this == 0 or this == null.
153                 //
154                 public virtual bool IsZeroInteger {
155                         get { return false; }
156                 }
157         }
158         
159         public class BoolConstant : Constant {
160                 public readonly bool Value;
161                 
162                 public BoolConstant (bool val)
163                 {
164                         type = TypeManager.bool_type;
165                         eclass = ExprClass.Value;
166
167                         Value = val;
168                 }
169
170                 override public string AsString ()
171                 {
172                         return Value ? "true" : "false";
173                 }
174
175                 public override object GetValue ()
176                 {
177                         return (object) Value;
178                 }
179                                 
180                 
181                 public override void Emit (EmitContext ec)
182                 {
183                         if (Value)
184                                 ec.ig.Emit (OpCodes.Ldc_I4_1);
185                         else
186                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
187                 }
188                 
189                 public override bool IsZeroInteger {
190                         get { return Value == false; }
191                 }
192         }
193
194         public class ByteConstant : Constant {
195                 public readonly byte Value;
196
197                 public ByteConstant (byte v)
198                 {
199                         type = TypeManager.byte_type;
200                         eclass = ExprClass.Value;
201                         Value = v;
202                 }
203
204                 public override void Emit (EmitContext ec)
205                 {
206                         IntLiteral.EmitInt (ec.ig, Value);
207                 }
208
209                 public override string AsString ()
210                 {
211                         return Value.ToString ();
212                 }
213
214                 public override object GetValue ()
215                 {
216                         return Value;
217                 }
218
219                 public override DoubleConstant ConvertToDouble ()
220                 {
221                         return new DoubleConstant (Value);
222                 }
223
224                 public override FloatConstant ConvertToFloat ()
225                 {
226                         return new FloatConstant (Value);
227                 }
228
229                 public override ULongConstant ConvertToULong ()
230                 {
231                         return new ULongConstant (Value);
232                 }
233
234                 public override LongConstant ConvertToLong ()
235                 {
236                         return new LongConstant (Value);
237                 }
238
239                 public override UIntConstant ConvertToUInt ()
240                 {
241                         return new UIntConstant (Value);
242                 }
243
244                 public override IntConstant ConvertToInt ()
245                 {
246                         return new IntConstant (Value);
247                 }
248                 
249                 public override bool IsZeroInteger {
250                         get { return Value == 0; }
251                 }
252         }
253
254         public class CharConstant : Constant {
255                 public readonly char Value;
256
257                 public CharConstant (char v)
258                 {
259                         type = TypeManager.char_type;
260                         eclass = ExprClass.Value;
261                         Value = v;
262                 }
263
264                 public override void Emit (EmitContext ec)
265                 {
266                         IntLiteral.EmitInt (ec.ig, Value);
267                 }
268
269                 static public string descape (char c)
270                 {
271                         switch (c){
272                         case '\a':
273                                 return "\\a"; 
274                         case '\b':
275                                 return "\\b"; 
276                         case '\n':
277                                 return "\\n"; 
278                         case '\t':
279                                 return "\\t"; 
280                         case '\v':
281                                 return "\\v"; 
282                         case '\r':
283                                 return "\\r"; 
284                         case '\\':
285                                 return "\\\\";
286                         case '\f':
287                                 return "\\f"; 
288                         case '\0':
289                                 return "\\0"; 
290                         case '"':
291                                 return "\\\""; 
292                         case '\'':
293                                 return "\\\'"; 
294                         }
295                         return c.ToString ();
296                 }
297
298                 public override string AsString ()
299                 {
300                         return "\"" + descape (Value) + "\"";
301                 }
302
303                 public override object GetValue ()
304                 {
305                         return Value;
306                 }
307
308                 public override DoubleConstant ConvertToDouble ()
309                 {
310                         return new DoubleConstant (Value);
311                 }
312
313                 public override FloatConstant ConvertToFloat ()
314                 {
315                         return new FloatConstant (Value);
316                 }
317
318                 public override ULongConstant ConvertToULong ()
319                 {
320                         return new ULongConstant (Value);
321                 }
322
323                 public override LongConstant ConvertToLong ()
324                 {
325                         return new LongConstant (Value);
326                 }
327
328                 public override UIntConstant ConvertToUInt ()
329                 {
330                         return new UIntConstant (Value);
331                 }
332
333                 public override IntConstant ConvertToInt ()
334                 {
335                         return new IntConstant (Value);
336                 }
337                 
338                 public override bool IsZeroInteger {
339                         get { return Value == '\0'; }
340                 }
341         }
342
343         public class SByteConstant : Constant {
344                 public readonly sbyte Value;
345
346                 public SByteConstant (sbyte v)
347                 {
348                         type = TypeManager.sbyte_type;
349                         eclass = ExprClass.Value;
350                         Value = v;
351                 }
352
353                 public override void Emit (EmitContext ec)
354                 {
355                         IntLiteral.EmitInt (ec.ig, Value);
356                 }
357
358                 public override string AsString ()
359                 {
360                         return Value.ToString ();
361                 }
362
363                 public override object GetValue ()
364                 {
365                         return Value;
366                 }
367
368                 public override DoubleConstant ConvertToDouble ()
369                 {
370                         return new DoubleConstant (Value);
371                 }
372
373                 public override FloatConstant ConvertToFloat ()
374                 {
375                         return new FloatConstant (Value);
376                 }
377
378                 public override ULongConstant ConvertToULong ()
379                 {
380                         if (Value >= 0)
381                                 return new ULongConstant ((ulong) Value);
382                         
383                         return null;
384                 }
385
386                 public override LongConstant ConvertToLong ()
387                 {
388                         return new LongConstant (Value);
389                 }
390
391                 public override UIntConstant ConvertToUInt ()
392                 {
393                         return null;
394                 }
395
396                 public override IntConstant ConvertToInt ()
397                 {
398                         return new IntConstant (Value);
399                 }
400                 
401                 public override bool IsZeroInteger {
402                         get { return Value == 0; }
403                 }
404         }
405
406         public class ShortConstant : Constant {
407                 public readonly short Value;
408
409                 public ShortConstant (short v)
410                 {
411                         type = TypeManager.short_type;
412                         eclass = ExprClass.Value;
413                         Value = v;
414                 }
415
416                 public override void Emit (EmitContext ec)
417                 {
418                         IntLiteral.EmitInt (ec.ig, Value);
419                 }
420
421                 public override string AsString ()
422                 {
423                         return Value.ToString ();
424                 }
425
426                 public override object GetValue ()
427                 {
428                         return Value;
429                 }
430
431                 public override DoubleConstant ConvertToDouble ()
432                 {
433                         return new DoubleConstant (Value);
434                 }
435
436                 public override FloatConstant ConvertToFloat ()
437                 {
438                         return new FloatConstant (Value);
439                 }
440
441                 public override ULongConstant ConvertToULong ()
442                 {
443                         return null;
444                 }
445
446                 public override LongConstant ConvertToLong ()
447                 {
448                         return new LongConstant (Value);
449                 }
450
451                 public override UIntConstant ConvertToUInt ()
452                 {
453                         return null;
454                 }
455
456                 public override IntConstant ConvertToInt ()
457                 {
458                         return new IntConstant (Value);
459                 }
460                 
461                 public override bool IsZeroInteger {
462                         get { return Value == 0; }
463                 }
464         }
465
466         public class UShortConstant : Constant {
467                 public readonly ushort Value;
468
469                 public UShortConstant (ushort v)
470                 {
471                         type = TypeManager.ushort_type;
472                         eclass = ExprClass.Value;
473                         Value = v;
474                 }
475
476                 public override void Emit (EmitContext ec)
477                 {
478                         IntLiteral.EmitInt (ec.ig, Value);
479                 }
480
481                 public override string AsString ()
482                 {
483                         return Value.ToString ();
484                 }
485
486                 public override object GetValue ()
487                 {
488                         return Value;
489                 }
490
491                 public override DoubleConstant ConvertToDouble ()
492                 {
493                         return new DoubleConstant (Value);
494                 }
495
496                 public override FloatConstant ConvertToFloat ()
497                 {
498                         return new FloatConstant (Value);
499                 }
500
501                 public override ULongConstant ConvertToULong ()
502                 {
503                         return new ULongConstant (Value);
504                 }
505
506                 public override LongConstant ConvertToLong ()
507                 {
508                         return new LongConstant (Value);
509                 }
510
511                 public override UIntConstant ConvertToUInt ()
512                 {
513                         return new UIntConstant (Value);
514                 }
515
516                 public override IntConstant ConvertToInt ()
517                 {
518                         return new IntConstant (Value);
519                 }
520                 
521                 public override bool IsZeroInteger {
522                         get { return Value == 0; }
523                 }
524         }
525
526         public class IntConstant : Constant {
527                 public readonly int Value;
528
529                 public IntConstant (int v)
530                 {
531                         type = TypeManager.int32_type;
532                         eclass = ExprClass.Value;
533                         Value = v;
534                 }
535
536                 static public void EmitInt (ILGenerator ig, int i)
537                 {
538                         switch (i){
539                         case -1:
540                                 ig.Emit (OpCodes.Ldc_I4_M1);
541                                 break;
542                                 
543                         case 0:
544                                 ig.Emit (OpCodes.Ldc_I4_0);
545                                 break;
546                                 
547                         case 1:
548                                 ig.Emit (OpCodes.Ldc_I4_1);
549                                 break;
550                                 
551                         case 2:
552                                 ig.Emit (OpCodes.Ldc_I4_2);
553                                 break;
554                                 
555                         case 3:
556                                 ig.Emit (OpCodes.Ldc_I4_3);
557                                 break;
558                                 
559                         case 4:
560                                 ig.Emit (OpCodes.Ldc_I4_4);
561                                 break;
562                                 
563                         case 5:
564                                 ig.Emit (OpCodes.Ldc_I4_5);
565                                 break;
566                                 
567                         case 6:
568                                 ig.Emit (OpCodes.Ldc_I4_6);
569                                 break;
570                                 
571                         case 7:
572                                 ig.Emit (OpCodes.Ldc_I4_7);
573                                 break;
574                                 
575                         case 8:
576                                 ig.Emit (OpCodes.Ldc_I4_8);
577                                 break;
578
579                         default:
580                                 if (i >= -128 && i <= 127){
581                                         ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
582                                 } else
583                                         ig.Emit (OpCodes.Ldc_I4, i);
584                                 break;
585                         }
586                 }
587
588                 public override void Emit (EmitContext ec)
589                 {
590                         EmitInt (ec.ig, Value);
591                 }
592
593                 public override string AsString ()
594                 {
595                         return Value.ToString ();
596                 }
597
598                 public override object GetValue ()
599                 {
600                         return Value;
601                 }
602
603                 public override DoubleConstant ConvertToDouble ()
604                 {
605                         return new DoubleConstant (Value);
606                 }
607
608                 public override FloatConstant ConvertToFloat ()
609                 {
610                         return new FloatConstant (Value);
611                 }
612
613                 public override ULongConstant ConvertToULong ()
614                 {
615                         if (Value < 0)
616                                 return null;
617
618                         return new ULongConstant ((ulong) Value);
619                 }
620
621                 public override LongConstant ConvertToLong ()
622                 {
623                         return new LongConstant (Value);
624                 }
625
626                 public override UIntConstant ConvertToUInt ()
627                 {
628                         if (Value < 0)
629                                 return null;
630
631                         return new UIntConstant ((uint) Value);
632                 }
633
634                 public override IntConstant ConvertToInt ()
635                 {
636                         return this;
637                 }
638                 
639                 public override bool IsZeroInteger {
640                         get { return Value == 0; }
641                 }
642         }
643
644         public class UIntConstant : Constant {
645                 public readonly uint Value;
646
647                 public UIntConstant (uint v)
648                 {
649                         type = TypeManager.uint32_type;
650                         eclass = ExprClass.Value;
651                         Value = v;
652                 }
653
654                 public override void Emit (EmitContext ec)
655                 {
656                         IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
657                 }
658
659                 public override string AsString ()
660                 {
661                         return Value.ToString ();
662                 }
663
664                 public override object GetValue ()
665                 {
666                         return Value;
667                 }
668
669                 public override DoubleConstant ConvertToDouble ()
670                 {
671                         return new DoubleConstant (Value);
672                 }
673
674                 public override FloatConstant ConvertToFloat ()
675                 {
676                         return new FloatConstant (Value);
677                 }
678
679                 public override ULongConstant ConvertToULong ()
680                 {
681                         return new ULongConstant (Value);
682                 }
683
684                 public override LongConstant ConvertToLong ()
685                 {
686                         return new LongConstant (Value);
687                 }
688
689                 public override UIntConstant ConvertToUInt ()
690                 {
691                         return this;
692                 }
693
694                 public override IntConstant ConvertToInt ()
695                 {
696                         return null;
697                 }
698                 
699                 public override bool IsZeroInteger {
700                         get { return Value == 0; }
701                 }
702         }
703
704         public class LongConstant : Constant {
705                 public readonly long Value;
706
707                 public LongConstant (long v)
708                 {
709                         type = TypeManager.int64_type;
710                         eclass = ExprClass.Value;
711                         Value = v;
712                 }
713
714                 public override void Emit (EmitContext ec)
715                 {
716                         ILGenerator ig = ec.ig;
717
718                         EmitLong (ig, Value);
719                 }
720
721                 static public void EmitLong (ILGenerator ig, long l)
722                 {
723                         if ((l >> 32) == 0){
724                                 IntLiteral.EmitInt (ig, unchecked ((int) l));
725                                 ig.Emit (OpCodes.Conv_U8);
726                         } else {
727                                 ig.Emit (OpCodes.Ldc_I8, l);
728                         }
729                 }
730
731                 public override string AsString ()
732                 {
733                         return Value.ToString ();
734                 }
735
736                 public override object GetValue ()
737                 {
738                         return Value;
739                 }
740
741                 public override DoubleConstant ConvertToDouble ()
742                 {
743                         return new DoubleConstant (Value);
744                 }
745
746                 public override FloatConstant ConvertToFloat ()
747                 {
748                         return new FloatConstant (Value);
749                 }
750
751                 public override ULongConstant ConvertToULong ()
752                 {
753                         if (Value < 0)
754                                 return null;
755                         
756                         return new ULongConstant ((ulong) Value);
757                 }
758
759                 public override LongConstant ConvertToLong ()
760                 {
761                         return this;
762                 }
763
764                 public override UIntConstant ConvertToUInt ()
765                 {
766                         return null;
767                 }
768
769                 public override IntConstant ConvertToInt ()
770                 {
771                         return null;
772                 }
773                 
774                 public override bool IsZeroInteger {
775                         get { return Value == 0; }
776                 }
777         }
778
779         public class ULongConstant : Constant {
780                 public readonly ulong Value;
781
782                 public ULongConstant (ulong v)
783                 {
784                         type = TypeManager.uint64_type;
785                         eclass = ExprClass.Value;
786                         Value = v;
787                 }
788
789                 public override void Emit (EmitContext ec)
790                 {
791                         ILGenerator ig = ec.ig;
792
793                         LongLiteral.EmitLong (ig, unchecked ((long) Value));
794                 }
795
796                 public override string AsString ()
797                 {
798                         return Value.ToString ();
799                 }
800
801                 public override object GetValue ()
802                 {
803                         return Value;
804                 }
805
806                 public override DoubleConstant ConvertToDouble ()
807                 {
808                         return new DoubleConstant (Value);
809                 }
810
811                 public override FloatConstant ConvertToFloat ()
812                 {
813                         return new FloatConstant (Value);
814                 }
815
816                 public override ULongConstant ConvertToULong ()
817                 {
818                         return this;
819                 }
820
821                 public override LongConstant ConvertToLong ()
822                 {
823                         return null;
824                 }
825
826                 public override UIntConstant ConvertToUInt ()
827                 {
828                         return null;
829                 }
830
831                 public override IntConstant ConvertToInt ()
832                 {
833                         return null;
834                 }
835                 
836                 public override bool IsZeroInteger {
837                         get { return Value == 0; }
838                 }
839         }
840
841         public class FloatConstant : Constant {
842                 public readonly float Value;
843
844                 public FloatConstant (float v)
845                 {
846                         type = TypeManager.float_type;
847                         eclass = ExprClass.Value;
848                         Value = v;
849                 }
850
851                 public override void Emit (EmitContext ec)
852                 {
853                         ec.ig.Emit (OpCodes.Ldc_R4, Value);
854                 }
855
856                 public override string AsString ()
857                 {
858                         return Value.ToString ();
859                 }
860
861                 public override object GetValue ()
862                 {
863                         return Value;
864                 }
865
866                 public override DoubleConstant ConvertToDouble ()
867                 {
868                         return new DoubleConstant (Value);
869                 }
870
871                 public override FloatConstant ConvertToFloat ()
872                 {
873                         return this;
874                 }
875
876                 public override LongConstant ConvertToLong ()
877                 {
878                         return null;
879                 }
880
881                 public override UIntConstant ConvertToUInt ()
882                 {
883                         return null;
884                 }
885
886                 public override IntConstant ConvertToInt ()
887                 {
888                         return null;
889                 }
890         }
891
892         public class DoubleConstant : Constant {
893                 public readonly double Value;
894
895                 public DoubleConstant (double v)
896                 {
897                         type = TypeManager.double_type;
898                         eclass = ExprClass.Value;
899                         Value = v;
900                 }
901
902                 public override void Emit (EmitContext ec)
903                 {
904                         ec.ig.Emit (OpCodes.Ldc_R8, Value);
905                 }
906
907                 public override string AsString ()
908                 {
909                         return Value.ToString ();
910                 }
911
912                 public override object GetValue ()
913                 {
914                         return Value;
915                 }
916
917                 public override DoubleConstant ConvertToDouble ()
918                 {
919                         return this;
920                 }
921
922                 public override FloatConstant ConvertToFloat ()
923                 {
924                         return null;
925                 }
926
927                 public override ULongConstant ConvertToULong ()
928                 {
929                         return null;
930                 }
931
932                 public override LongConstant ConvertToLong ()
933                 {
934                         return null;
935                 }
936
937                 public override UIntConstant ConvertToUInt ()
938                 {
939                         return null;
940                 }
941
942                 public override IntConstant ConvertToInt ()
943                 {
944                         return null;
945                 }
946         }
947
948         public class DecimalConstant : Constant {
949                 public readonly decimal Value;
950
951                 public DecimalConstant (decimal d)
952                 {
953                         type = TypeManager.decimal_type;
954                         eclass = ExprClass.Value;
955                         Value = d;
956                 }
957
958                 override public string AsString ()
959                 {
960                         return Value.ToString ();
961                 }
962
963                 public override object GetValue ()
964                 {
965                         return (object) Value;
966                 }
967
968                 public override void Emit (EmitContext ec)
969                 {
970                         int [] words = Decimal.GetBits (Value);
971                         
972                         //
973                         // FIXME: we could optimize this, and call a better 
974                         // constructor
975                         //
976
977                         ILGenerator ig = ec.ig;
978                         
979                         IntConstant.EmitInt (ig, words [0]);
980                         IntConstant.EmitInt (ig, words [1]);
981                         IntConstant.EmitInt (ig, words [2]);
982
983                         // sign
984                         IntConstant.EmitInt (ig, words [3] >> 31);
985
986                         // power
987                         IntConstant.EmitInt (ig, (words [3] >> 16) & 0xff);
988
989                         ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
990                 }
991         }
992
993         public class StringConstant : Constant {
994                 public readonly string Value;
995
996                 public StringConstant (string s)
997                 {
998                         type = TypeManager.string_type;
999                         eclass = ExprClass.Value;
1000                         Value = s;
1001                 }
1002
1003                 // FIXME: Escape the string.
1004                 override public string AsString ()
1005                 {
1006                         return "\"" + Value + "\"";
1007                 }
1008
1009                 public override object GetValue ()
1010                 {
1011                         return Value;
1012                 }
1013                 
1014                 public override void Emit (EmitContext ec)
1015                 {
1016                         if (Value == null)
1017                                 ec.ig.Emit (OpCodes.Ldnull);
1018                         else
1019                                 ec.ig.Emit (OpCodes.Ldstr, Value);
1020                 }
1021         }
1022
1023 }
1024
1025