2 // constant.cs: Constants.
5 // Miguel de Icaza (miguel@ximian.com)
7 // (C) 2001 Ximian, Inc.
11 namespace Mono.MonoBASIC {
14 using System.Reflection.Emit;
17 /// Base class for constants and literals.
19 public abstract class Constant : Expression {
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.
28 public abstract string AsString ();
30 override public string ToString ()
32 return this.GetType ().Name + " (" + AsString () + ")";
36 /// This is used to obtain the actual value of the literal
37 /// cast into an object.
39 public abstract object GetValue ();
42 /// Constants are always born in a fully resolved state
44 public override Expression DoResolve (EmitContext ec)
50 // The various ToXXXX conversion functions are used by the constant
51 // folding evaluator. A null value is returned if the conversion is
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).
60 public DoubleConstant ToDouble (Location loc)
62 DoubleConstant c = ConvertToDouble ();
65 Error_CannotConvertImplicit (loc, Type, TypeManager.double_type);
70 public FloatConstant ToFloat (Location loc)
72 FloatConstant c = ConvertToFloat ();
75 Error_CannotConvertImplicit (loc, Type, TypeManager.float_type);
80 public ULongConstant ToULong (Location loc)
82 ULongConstant c = ConvertToULong ();
85 Error_CannotConvertImplicit (loc, Type, TypeManager.uint64_type);
90 public LongConstant ToLong (Location loc)
92 LongConstant c = ConvertToLong ();
95 Error_CannotConvertImplicit (loc, Type, TypeManager.int64_type);
100 public UIntConstant ToUInt (Location loc)
102 UIntConstant c = ConvertToUInt ();
105 Error_CannotConvertImplicit (loc, Type, TypeManager.uint32_type);
110 public IntConstant ToInt (Location loc)
112 IntConstant c = ConvertToInt ();
115 Error_CannotConvertImplicit (loc, Type, TypeManager.int32_type);
120 public DecimalConstant ToDecimal (Location loc)
122 DecimalConstant c = ConvertToDecimal ();
125 Error_CannotConvertImplicit (loc, Type, TypeManager.decimal_type);
130 public virtual DecimalConstant ConvertToDecimal ()
136 public virtual DoubleConstant ConvertToDouble ()
141 public virtual FloatConstant ConvertToFloat ()
146 public virtual ULongConstant ConvertToULong ()
151 public virtual LongConstant ConvertToLong ()
156 public virtual UIntConstant ConvertToUInt ()
161 public virtual IntConstant ConvertToInt ()
167 public class BoolConstant : Constant {
168 public readonly bool Value;
170 public BoolConstant (bool val)
172 type = TypeManager.bool_type;
173 eclass = ExprClass.Value;
178 override public string AsString ()
180 return Value ? "true" : "false";
183 public override object GetValue ()
185 return (object) Value;
189 public override void Emit (EmitContext ec)
192 ec.ig.Emit (OpCodes.Ldc_I4_1);
194 ec.ig.Emit (OpCodes.Ldc_I4_0);
198 public class ByteConstant : Constant {
199 public readonly byte Value;
201 public ByteConstant (byte v)
203 type = TypeManager.byte_type;
204 eclass = ExprClass.Value;
208 public override void Emit (EmitContext ec)
210 IntLiteral.EmitInt (ec.ig, Value);
213 public override string AsString ()
215 return Value.ToString ();
218 public override object GetValue ()
223 public override DoubleConstant ConvertToDouble ()
225 return new DoubleConstant (Value);
228 public override FloatConstant ConvertToFloat ()
230 return new FloatConstant (Value);
233 public override ULongConstant ConvertToULong ()
235 return new ULongConstant (Value);
238 public override LongConstant ConvertToLong ()
240 return new LongConstant (Value);
243 public override UIntConstant ConvertToUInt ()
245 return new UIntConstant (Value);
248 public override IntConstant ConvertToInt ()
250 return new IntConstant (Value);
254 public class CharConstant : Constant {
255 public readonly char Value;
257 public CharConstant (char v)
259 type = TypeManager.char_type;
260 eclass = ExprClass.Value;
264 public override void Emit (EmitContext ec)
266 IntLiteral.EmitInt (ec.ig, Value);
269 static public string descape (char c)
295 return c.ToString ();
298 public override string AsString ()
300 return "\"" + descape (Value) + "\"";
303 public override object GetValue ()
308 public override DoubleConstant ConvertToDouble ()
310 return new DoubleConstant (Value);
313 public override FloatConstant ConvertToFloat ()
315 return new FloatConstant (Value);
318 public override ULongConstant ConvertToULong ()
320 return new ULongConstant (Value);
323 public override LongConstant ConvertToLong ()
325 return new LongConstant (Value);
328 public override UIntConstant ConvertToUInt ()
330 return new UIntConstant (Value);
333 public override IntConstant ConvertToInt ()
335 return new IntConstant (Value);
339 public class SByteConstant : Constant {
340 public readonly sbyte Value;
342 public SByteConstant (sbyte v)
344 type = TypeManager.sbyte_type;
345 eclass = ExprClass.Value;
349 public override void Emit (EmitContext ec)
351 IntLiteral.EmitInt (ec.ig, Value);
354 public override string AsString ()
356 return Value.ToString ();
359 public override object GetValue ()
364 public override DoubleConstant ConvertToDouble ()
366 return new DoubleConstant (Value);
369 public override FloatConstant ConvertToFloat ()
371 return new FloatConstant (Value);
374 public override ULongConstant ConvertToULong ()
377 return new ULongConstant ((ulong) Value);
382 public override LongConstant ConvertToLong ()
384 return new LongConstant (Value);
387 public override UIntConstant ConvertToUInt ()
392 public override IntConstant ConvertToInt ()
394 return new IntConstant (Value);
398 public class ShortConstant : Constant {
399 public readonly short Value;
401 public ShortConstant (short v)
403 type = TypeManager.short_type;
404 eclass = ExprClass.Value;
408 public override void Emit (EmitContext ec)
410 IntLiteral.EmitInt (ec.ig, Value);
413 public override string AsString ()
415 return Value.ToString ();
418 public override object GetValue ()
423 public override DoubleConstant ConvertToDouble ()
425 return new DoubleConstant (Value);
428 public override FloatConstant ConvertToFloat ()
430 return new FloatConstant (Value);
433 public override ULongConstant ConvertToULong ()
438 public override LongConstant ConvertToLong ()
440 return new LongConstant (Value);
443 public override UIntConstant ConvertToUInt ()
448 public override IntConstant ConvertToInt ()
450 return new IntConstant (Value);
454 public class UShortConstant : Constant {
455 public readonly ushort Value;
457 public UShortConstant (ushort v)
459 type = TypeManager.ushort_type;
460 eclass = ExprClass.Value;
464 public override void Emit (EmitContext ec)
466 IntLiteral.EmitInt (ec.ig, Value);
469 public override string AsString ()
471 return Value.ToString ();
474 public override object GetValue ()
479 public override DoubleConstant ConvertToDouble ()
481 return new DoubleConstant (Value);
484 public override FloatConstant ConvertToFloat ()
486 return new FloatConstant (Value);
489 public override ULongConstant ConvertToULong ()
491 return new ULongConstant (Value);
494 public override LongConstant ConvertToLong ()
496 return new LongConstant (Value);
499 public override UIntConstant ConvertToUInt ()
501 return new UIntConstant (Value);
504 public override IntConstant ConvertToInt ()
506 return new IntConstant (Value);
510 public class IntConstant : Constant {
511 public readonly int Value;
513 public IntConstant (int v)
515 type = TypeManager.int32_type;
516 eclass = ExprClass.Value;
520 static public void EmitInt (ILGenerator ig, int i)
524 ig.Emit (OpCodes.Ldc_I4_M1);
528 ig.Emit (OpCodes.Ldc_I4_0);
532 ig.Emit (OpCodes.Ldc_I4_1);
536 ig.Emit (OpCodes.Ldc_I4_2);
540 ig.Emit (OpCodes.Ldc_I4_3);
544 ig.Emit (OpCodes.Ldc_I4_4);
548 ig.Emit (OpCodes.Ldc_I4_5);
552 ig.Emit (OpCodes.Ldc_I4_6);
556 ig.Emit (OpCodes.Ldc_I4_7);
560 ig.Emit (OpCodes.Ldc_I4_8);
564 if (i >= -128 && i <= 127){
565 ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
567 ig.Emit (OpCodes.Ldc_I4, i);
572 public override void Emit (EmitContext ec)
574 EmitInt (ec.ig, Value);
577 public override string AsString ()
579 return Value.ToString ();
582 public override object GetValue ()
587 public override DoubleConstant ConvertToDouble ()
589 return new DoubleConstant (Value);
592 public override FloatConstant ConvertToFloat ()
594 return new FloatConstant (Value);
597 public override ULongConstant ConvertToULong ()
602 return new ULongConstant ((ulong) Value);
605 public override LongConstant ConvertToLong ()
607 return new LongConstant (Value);
610 public override UIntConstant ConvertToUInt ()
615 return new UIntConstant ((uint) Value);
618 public override IntConstant ConvertToInt ()
624 public class UIntConstant : Constant {
625 public readonly uint Value;
627 public UIntConstant (uint v)
629 type = TypeManager.uint32_type;
630 eclass = ExprClass.Value;
634 public override void Emit (EmitContext ec)
636 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
639 public override string AsString ()
641 return Value.ToString ();
644 public override object GetValue ()
649 public override DoubleConstant ConvertToDouble ()
651 return new DoubleConstant (Value);
654 public override FloatConstant ConvertToFloat ()
656 return new FloatConstant (Value);
659 public override ULongConstant ConvertToULong ()
661 return new ULongConstant (Value);
664 public override LongConstant ConvertToLong ()
666 return new LongConstant (Value);
669 public override UIntConstant ConvertToUInt ()
674 public override IntConstant ConvertToInt ()
680 public class LongConstant : Constant {
681 public readonly long Value;
683 public LongConstant (long v)
685 type = TypeManager.int64_type;
686 eclass = ExprClass.Value;
690 public override void Emit (EmitContext ec)
692 ILGenerator ig = ec.ig;
694 EmitLong (ig, Value);
697 static public void EmitLong (ILGenerator ig, long l)
699 ig.Emit (OpCodes.Ldc_I8, l);
702 public override string AsString ()
704 return Value.ToString ();
707 public override object GetValue ()
712 public override DoubleConstant ConvertToDouble ()
714 return new DoubleConstant (Value);
717 public override FloatConstant ConvertToFloat ()
719 return new FloatConstant (Value);
722 public override ULongConstant ConvertToULong ()
727 return new ULongConstant ((ulong) Value);
730 public override LongConstant ConvertToLong ()
735 public override UIntConstant ConvertToUInt ()
740 public override IntConstant ConvertToInt ()
746 public class ULongConstant : Constant {
747 public readonly ulong Value;
749 public ULongConstant (ulong v)
751 type = TypeManager.uint64_type;
752 eclass = ExprClass.Value;
756 public override void Emit (EmitContext ec)
758 ILGenerator ig = ec.ig;
760 LongLiteral.EmitLong (ig, unchecked ((long) Value));
763 public override string AsString ()
765 return Value.ToString ();
768 public override object GetValue ()
773 public override DoubleConstant ConvertToDouble ()
775 return new DoubleConstant (Value);
778 public override FloatConstant ConvertToFloat ()
780 return new FloatConstant (Value);
783 public override ULongConstant ConvertToULong ()
788 public override LongConstant ConvertToLong ()
793 public override UIntConstant ConvertToUInt ()
798 public override IntConstant ConvertToInt ()
804 public class FloatConstant : Constant {
805 public readonly float Value;
807 public FloatConstant (float v)
809 type = TypeManager.float_type;
810 eclass = ExprClass.Value;
814 public override void Emit (EmitContext ec)
816 ec.ig.Emit (OpCodes.Ldc_R4, Value);
819 public override string AsString ()
821 return Value.ToString ();
824 public override object GetValue ()
829 public override DoubleConstant ConvertToDouble ()
831 return new DoubleConstant (Value);
834 public override FloatConstant ConvertToFloat ()
839 public override LongConstant ConvertToLong ()
844 public override UIntConstant ConvertToUInt ()
849 public override IntConstant ConvertToInt ()
855 public class DoubleConstant : Constant {
856 public readonly double Value;
858 public DoubleConstant (double v)
860 type = TypeManager.double_type;
861 eclass = ExprClass.Value;
865 public override void Emit (EmitContext ec)
867 ec.ig.Emit (OpCodes.Ldc_R8, Value);
870 public override string AsString ()
872 return Value.ToString ();
875 public override object GetValue ()
880 public override DoubleConstant ConvertToDouble ()
885 public override FloatConstant ConvertToFloat ()
890 public override ULongConstant ConvertToULong ()
895 public override LongConstant ConvertToLong ()
900 public override UIntConstant ConvertToUInt ()
905 public override IntConstant ConvertToInt ()
911 public class DecimalConstant : Constant {
912 public readonly decimal Value;
914 public DecimalConstant (decimal d)
916 type = TypeManager.decimal_type;
917 eclass = ExprClass.Value;
921 override public string AsString ()
923 return Value.ToString ();
926 public override object GetValue ()
928 return (object) Value;
931 public override void Emit (EmitContext ec)
933 ILGenerator ig = ec.ig;
936 int [] words = Decimal.GetBits (Value);
937 int power = (words [3] >> 16) & 0xff;
939 if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
941 IntConstant.EmitInt (ig, (int)Value);
942 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
949 // FIXME: we could optimize this, and call a better
953 IntConstant.EmitInt (ig, words [0]);
954 IntConstant.EmitInt (ig, words [1]);
955 IntConstant.EmitInt (ig, words [2]);
958 IntConstant.EmitInt (ig, words [3] >> 31);
961 IntConstant.EmitInt (ig, power);
963 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
968 public class StringConstant : Constant {
969 public readonly string Value;
971 public StringConstant (string s)
973 type = TypeManager.string_type;
974 eclass = ExprClass.Value;
978 // FIXME: Escape the string.
979 override public string AsString ()
981 return "\"" + Value + "\"";
984 public override object GetValue ()
989 public override void Emit (EmitContext ec)
991 ec.ig.Emit (OpCodes.Ldstr, Value);
995 public class DateConstant : Constant {
996 public readonly DateTime Value;
998 public DateConstant (DateTime s)
1000 type = TypeManager.date_type;
1001 eclass = ExprClass.Value;
1005 override public string AsString ()
1007 return "#" + Value.ToString() + "#";
1010 public override object GetValue ()
1015 public override void Emit (EmitContext ec)
1017 ec.ig.Emit (OpCodes.Ldc_I8, Value.Ticks);
1018 ec.ig.Emit (OpCodes.Newobj, TypeManager.void_datetime_ctor_ticks_arg);