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