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 DecimalConstant ConvertToDecimal ()
599 return new DecimalConstant (Value);
602 public override ULongConstant ConvertToULong ()
607 return new ULongConstant ((ulong) Value);
610 public override LongConstant ConvertToLong ()
612 return new LongConstant (Value);
615 public override UIntConstant ConvertToUInt ()
620 return new UIntConstant ((uint) Value);
623 public override IntConstant ConvertToInt ()
629 public class UIntConstant : Constant {
630 public readonly uint Value;
632 public UIntConstant (uint v)
634 type = TypeManager.uint32_type;
635 eclass = ExprClass.Value;
639 public override void Emit (EmitContext ec)
641 IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
644 public override string AsString ()
646 return Value.ToString ();
649 public override object GetValue ()
654 public override DoubleConstant ConvertToDouble ()
656 return new DoubleConstant (Value);
659 public override FloatConstant ConvertToFloat ()
661 return new FloatConstant (Value);
664 public override ULongConstant ConvertToULong ()
666 return new ULongConstant (Value);
669 public override LongConstant ConvertToLong ()
671 return new LongConstant (Value);
674 public override UIntConstant ConvertToUInt ()
679 public override IntConstant ConvertToInt ()
685 public class LongConstant : Constant {
686 public readonly long Value;
688 public LongConstant (long v)
690 type = TypeManager.int64_type;
691 eclass = ExprClass.Value;
695 public override void Emit (EmitContext ec)
697 ILGenerator ig = ec.ig;
699 EmitLong (ig, Value);
702 static public void EmitLong (ILGenerator ig, long l)
704 ig.Emit (OpCodes.Ldc_I8, l);
707 public override string AsString ()
709 return Value.ToString ();
712 public override object GetValue ()
717 public override DoubleConstant ConvertToDouble ()
719 return new DoubleConstant (Value);
722 public override FloatConstant ConvertToFloat ()
724 return new FloatConstant (Value);
727 public override ULongConstant ConvertToULong ()
732 return new ULongConstant ((ulong) Value);
735 public override LongConstant ConvertToLong ()
740 public override UIntConstant ConvertToUInt ()
745 public override IntConstant ConvertToInt ()
751 public class ULongConstant : Constant {
752 public readonly ulong Value;
754 public ULongConstant (ulong v)
756 type = TypeManager.uint64_type;
757 eclass = ExprClass.Value;
761 public override void Emit (EmitContext ec)
763 ILGenerator ig = ec.ig;
765 LongLiteral.EmitLong (ig, unchecked ((long) Value));
768 public override string AsString ()
770 return Value.ToString ();
773 public override object GetValue ()
778 public override DoubleConstant ConvertToDouble ()
780 return new DoubleConstant (Value);
783 public override FloatConstant ConvertToFloat ()
785 return new FloatConstant (Value);
788 public override ULongConstant ConvertToULong ()
793 public override LongConstant ConvertToLong ()
798 public override UIntConstant ConvertToUInt ()
803 public override IntConstant ConvertToInt ()
809 public class FloatConstant : Constant {
810 public readonly float Value;
812 public FloatConstant (float v)
814 type = TypeManager.float_type;
815 eclass = ExprClass.Value;
819 public override void Emit (EmitContext ec)
821 ec.ig.Emit (OpCodes.Ldc_R4, Value);
824 public override string AsString ()
826 return Value.ToString ();
829 public override object GetValue ()
834 public override DoubleConstant ConvertToDouble ()
836 return new DoubleConstant (Value);
839 public override FloatConstant ConvertToFloat ()
844 public override LongConstant ConvertToLong ()
849 public override UIntConstant ConvertToUInt ()
854 public override IntConstant ConvertToInt ()
860 public class DoubleConstant : Constant {
861 public readonly double Value;
863 public DoubleConstant (double v)
865 type = TypeManager.double_type;
866 eclass = ExprClass.Value;
870 public override void Emit (EmitContext ec)
872 ec.ig.Emit (OpCodes.Ldc_R8, Value);
875 public override string AsString ()
877 return Value.ToString ();
880 public override object GetValue ()
885 public override DoubleConstant ConvertToDouble ()
890 public override FloatConstant ConvertToFloat ()
892 return new FloatConstant ((float) Value);
895 public override DecimalConstant ConvertToDecimal ()
897 return new DecimalConstant ((decimal) Value);
900 public override ULongConstant ConvertToULong ()
905 public override LongConstant ConvertToLong ()
910 public override UIntConstant ConvertToUInt ()
915 public override IntConstant ConvertToInt ()
921 public class DecimalConstant : Constant {
922 public readonly decimal Value;
924 public DecimalConstant (decimal d)
926 type = TypeManager.decimal_type;
927 eclass = ExprClass.Value;
931 override public string AsString ()
933 return Value.ToString ();
936 public override object GetValue ()
938 return (object) Value;
941 public override void Emit (EmitContext ec)
943 ILGenerator ig = ec.ig;
946 int [] words = Decimal.GetBits (Value);
947 int power = (words [3] >> 16) & 0xff;
949 if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
951 IntConstant.EmitInt (ig, (int)Value);
952 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
959 // FIXME: we could optimize this, and call a better
963 IntConstant.EmitInt (ig, words [0]);
964 IntConstant.EmitInt (ig, words [1]);
965 IntConstant.EmitInt (ig, words [2]);
968 IntConstant.EmitInt (ig, words [3] >> 31);
971 IntConstant.EmitInt (ig, power);
973 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
978 public class StringConstant : Constant {
979 public readonly string Value;
981 public StringConstant (string s)
983 type = TypeManager.string_type;
984 eclass = ExprClass.Value;
988 // FIXME: Escape the string.
989 override public string AsString ()
991 return "\"" + Value + "\"";
994 public override object GetValue ()
999 public override void Emit (EmitContext ec)
1001 ec.ig.Emit (OpCodes.Ldstr, Value);
1005 public class DateConstant : Constant {
1006 public readonly DateTime Value;
1008 public DateConstant (DateTime s)
1010 type = TypeManager.date_type;
1011 eclass = ExprClass.Value;
1015 override public string AsString ()
1017 return "#" + Value.ToString() + "#";
1020 public override object GetValue ()
1025 public override void Emit (EmitContext ec)
1027 ec.ig.Emit (OpCodes.Ldc_I8, Value.Ticks);
1028 ec.ig.Emit (OpCodes.Newobj, TypeManager.void_datetime_ctor_ticks_arg);