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