2007-01-03 Chris Toshok <toshok@ximian.com>
[mono.git] / mcs / mcs / constant.cs
1 //
2 // constant.cs: Constants.
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //   Marek Safar (marek.safar@seznam.cz)
7 //
8 // (C) 2001 Ximian, Inc.
9 //
10 //
11
12 namespace Mono.CSharp {
13
14         using System;
15         using System.Reflection.Emit;
16
17         /// <summary>
18         ///   Base class for constants and literals.
19         /// </summary>
20         public abstract class Constant : Expression {
21
22                 protected Constant (Location loc)
23                 {
24                         this.loc = loc;
25                 }
26
27                 /// <remarks>
28                 ///   This is different from ToString in that ToString
29                 ///   is supposed to be there for debugging purposes,
30                 ///   and is not guaranteed to be useful for anything else,
31                 ///   AsString() will provide something that can be used
32                 ///   for round-tripping C# code.  Maybe it can be used
33                 ///   for IL assembly as well.
34                 /// </remarks>
35                 public abstract string AsString ();
36
37                 override public string ToString ()
38                 {
39                         return this.GetType ().Name + " (" + AsString () + ")";
40                 }
41
42                 public override bool GetAttributableValue (Type valueType, out object value)
43                 {
44                         Constant c = ImplicitConversionRequired (valueType, loc);
45                         if (c == null) {
46                                 value = null;
47                                 return false;
48                         }
49
50                         value = c.GetTypedValue ();
51                         return true;
52                 }
53
54                 /// <summary>
55                 ///  This is used to obtain the actual value of the literal
56                 ///  cast into an object.
57                 /// </summary>
58                 public abstract object GetValue ();
59
60                 public virtual object GetTypedValue ()
61                 {
62                         return GetValue ();
63                 }
64
65                 /// <summary>
66                 ///   Constants are always born in a fully resolved state
67                 /// </summary>
68                 public override Expression DoResolve (EmitContext ec)
69                 {
70                         return this;
71                 }
72
73                 public Constant ImplicitConversionRequired (Type type, Location loc)
74                 {
75                         Constant c = ConvertImplicitly (type);
76                         if (c == null)
77                                 Error_ValueCannotBeConverted (null, loc, type, false);
78                         return c;
79                 }
80
81                 public virtual Constant ConvertImplicitly (Type type)
82                 {
83                         if (this.type == type)
84                                 return this;
85
86                         if (type == TypeManager.object_type)
87                                 return new EmptyConstantCast (this, type);
88
89                         if (Convert.ImplicitNumericConversion (this, type) == null) 
90                                 return null;
91
92                         bool fail;                      
93                         object constant_value = TypeManager.ChangeType (GetValue (), type, out fail);
94                         if (fail){
95                                 //
96                                 // We should always catch the error before this is ever
97                                 // reached, by calling Convert.ImplicitStandardConversionExists
98                                 //
99                                 throw new Exception (
100                                         String.Format ("LookupConstantValue: This should never be reached {0} {1}", Type, type));
101                         }
102
103                         return CreateConstant (type, constant_value, loc);
104                 }
105
106                 ///  Returns a constant instance based on Type
107                 ///  The returned value is already resolved.
108                 public static Constant CreateConstant (Type t, object v, Location loc)
109                 {
110                         if (t == TypeManager.int32_type)
111                                 return new IntConstant ((int) v, loc);
112                         if (t == TypeManager.string_type)
113                                 return new StringConstant ((string) v, loc);
114                         if (t == TypeManager.uint32_type)
115                                 return new UIntConstant ((uint) v, loc);
116                         if (t == TypeManager.int64_type)
117                                 return new LongConstant ((long) v, loc);
118                         if (t == TypeManager.uint64_type)
119                                 return new ULongConstant ((ulong) v, loc);
120                         if (t == TypeManager.float_type)
121                                 return new FloatConstant ((float) v, loc);
122                         if (t == TypeManager.double_type)
123                                 return new DoubleConstant ((double) v, loc);
124                         if (t == TypeManager.short_type)
125                                 return new ShortConstant ((short)v, loc);
126                         if (t == TypeManager.ushort_type)
127                                 return new UShortConstant ((ushort)v, loc);
128                         if (t == TypeManager.sbyte_type)
129                                 return new SByteConstant ((sbyte)v, loc);
130                         if (t == TypeManager.byte_type)
131                                 return new ByteConstant ((byte)v, loc);
132                         if (t == TypeManager.char_type)
133                                 return new CharConstant ((char)v, loc);
134                         if (t == TypeManager.bool_type)
135                                 return new BoolConstant ((bool) v, loc);
136                         if (t == TypeManager.decimal_type)
137                                 return new DecimalConstant ((decimal) v, loc);
138                         if (TypeManager.IsEnumType (t)) {
139                                 Type real_type = TypeManager.TypeToCoreType (v.GetType ());
140                                 if (real_type == t)
141                                         real_type = System.Enum.GetUnderlyingType (real_type);
142                                 return new EnumConstant (CreateConstant (real_type, v, loc), t);
143                         } 
144                         if (v == null && !TypeManager.IsValueType (t))
145                                 return new EmptyConstantCast (new NullConstant (loc), t);
146
147                         throw new Exception ("Unknown type for constant (" + t +
148                                         "), details: " + v);
149                 }
150
151                 protected static void CheckRange (bool inCheckedContext, ulong value, ulong max)
152                 {
153                         if (!inCheckedContext)
154                                 return;
155
156                         if (value > max)
157                                 throw new OverflowException ();
158                 }
159
160                 protected static void CheckRange (bool inCheckedContext, double value, long min, long max)
161                 {
162                         if (!inCheckedContext)
163                                 return;
164
165                         if (((value < min) || (value > max)))
166                                 throw new OverflowException ();
167
168                         if (double.IsNaN (value))
169                                 throw new OverflowException ();
170                 }
171
172                 protected static void CheckRange (bool inCheckedContext, double value, ulong min, ulong max)
173                 {
174                         if (!inCheckedContext)
175                                 return;
176
177                         if (((value < min) || (value > max)))
178                                 throw new OverflowException ();
179
180                         if (double.IsNaN (value))
181                                 throw new OverflowException ();
182                 }
183
184                 protected static void CheckUnsigned (bool inCheckedContext, long value)
185                 {
186                         if (!inCheckedContext)
187                                 return;
188
189                         if (value < 0)
190                                 throw new OverflowException ();
191                 }
192
193                 /// <summary>
194                 /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type.
195                 /// It throws OverflowException 
196                 /// </summary>
197                 // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS
198                 public abstract Constant ConvertExplicitly (bool inCheckedContext, Type target_type);
199
200                 /// <summary>
201                 ///   Attempts to do a compile-time folding of a constant cast.
202                 /// </summary>
203                 public Constant TryReduce (EmitContext ec, Type target_type, Location loc)
204                 {
205                         try {
206                                 return TryReduce (ec, target_type);
207                         }
208                         catch (OverflowException) {
209                                 Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
210                                         GetValue ().ToString (), TypeManager.CSharpName (target_type));
211                                 return null;
212                         }
213                 }
214
215                 Constant TryReduce (EmitContext ec, Type target_type)
216                 {
217                         if (Type == target_type)
218                                 return this;
219
220                         if (TypeManager.IsEnumType (target_type)) {
221                                 Constant c = TryReduce (ec, TypeManager.EnumToUnderlying (target_type));
222                                 if (c == null)
223                                         return null;
224
225                                 return new EnumConstant (c, target_type);
226                         }
227
228                         return ConvertExplicitly (ec.ConstantCheckState, target_type);
229                 }
230
231                 public abstract Constant Increment ();
232                 
233                 /// <summary>
234                 /// Need to pass type as the constant can require a boxing
235                 /// and in such case no optimization is possible
236                 /// </summary>
237                 public bool IsDefaultInitializer (Type type)
238                 {
239                         if (type == Type)
240                                 return IsDefaultValue;
241
242                         return Type == TypeManager.null_type;
243                 }
244
245                 public abstract bool IsDefaultValue {
246                         get;
247                 }
248
249                 public abstract bool IsNegative {
250                         get;
251                 }
252
253                 //
254                 // Returns true iff 1) the stack type of this is one of Object, 
255                 // int32, int64 and 2) this == 0 or this == null.
256                 //
257                 public virtual bool IsZeroInteger {
258                         get { return false; }
259                 }
260         }
261
262         public abstract class IntegralConstant : Constant {
263                 protected IntegralConstant (Location loc) :
264                         base (loc)
265                 {
266                 }
267
268                 public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl)
269                 {
270                         try {
271                                 ConvertExplicitly (true, target);
272                                 base.Error_ValueCannotBeConverted (ec, loc, target, expl);
273                         }
274                         catch
275                         {
276                                 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
277                                         GetValue ().ToString (), TypeManager.CSharpName (target));
278                         }
279                 }
280         }
281         
282         public class BoolConstant : Constant {
283                 public readonly bool Value;
284                 
285                 public BoolConstant (bool val, Location loc):
286                         base (loc)
287                 {
288                         type = TypeManager.bool_type;
289                         eclass = ExprClass.Value;
290
291                         Value = val;
292                 }
293
294                 override public string AsString ()
295                 {
296                         return Value ? "true" : "false";
297                 }
298
299                 public override object GetValue ()
300                 {
301                         return (object) Value;
302                 }
303                                 
304                 
305                 public override void Emit (EmitContext ec)
306                 {
307                         if (Value)
308                                 ec.ig.Emit (OpCodes.Ldc_I4_1);
309                         else
310                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
311                 }
312
313                 public override Constant Increment ()
314                 {
315                         throw new NotSupportedException ();
316                 }
317         
318                 public override bool IsDefaultValue {
319                         get {
320                                 return !Value;
321                         }
322                 }
323
324                 public override bool IsNegative {
325                         get {
326                                 return false;
327                         }
328                 }
329         
330                 public override bool IsZeroInteger {
331                         get { return Value == false; }
332                 }
333
334                 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
335                 {
336                         return null;
337                 }
338
339         }
340
341         public class ByteConstant : IntegralConstant {
342                 public readonly byte Value;
343
344                 public ByteConstant (byte v, Location loc):
345                         base (loc)
346                 {
347                         type = TypeManager.byte_type;
348                         eclass = ExprClass.Value;
349                         Value = v;
350                 }
351
352                 public override void Emit (EmitContext ec)
353                 {
354                         IntLiteral.EmitInt (ec.ig, Value);
355                 }
356
357                 public override string AsString ()
358                 {
359                         return Value.ToString ();
360                 }
361
362                 public override object GetValue ()
363                 {
364                         return Value;
365                 }
366
367                 public override Constant Increment ()
368                 {
369                         return new ByteConstant (checked ((byte)(Value + 1)), loc);
370                 }
371
372                 public override bool IsDefaultValue {
373                         get {
374                                 return Value == 0;
375                         }
376                 }
377
378                 public override bool IsNegative {
379                         get {
380                                 return false;
381                         }
382                 }
383
384                 public override bool IsZeroInteger {
385                         get { return Value == 0; }
386                 }
387
388                 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
389                 {
390                         if (target_type == TypeManager.sbyte_type) {
391                                 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
392                                 return new SByteConstant ((sbyte) Value, Location);
393                         }
394                         if (target_type == TypeManager.short_type)
395                                 return new ShortConstant ((short) Value, Location);
396                         if (target_type == TypeManager.ushort_type)
397                                 return new UShortConstant ((ushort) Value, Location);
398                         if (target_type == TypeManager.int32_type)
399                                 return new IntConstant ((int) Value, Location);
400                         if (target_type == TypeManager.uint32_type)
401                                 return new UIntConstant ((uint) Value, Location);
402                         if (target_type == TypeManager.int64_type)
403                                 return new LongConstant ((long) Value, Location);
404                         if (target_type == TypeManager.uint64_type)
405                                 return new ULongConstant ((ulong) Value, Location);
406                         if (target_type == TypeManager.float_type)
407                                 return new FloatConstant ((float) Value, Location);
408                         if (target_type == TypeManager.double_type)
409                                 return new DoubleConstant ((double) Value, Location);
410                         if (target_type == TypeManager.char_type)
411                                 return new CharConstant ((char) Value, Location);
412                         if (target_type == TypeManager.decimal_type)
413                                 return new DecimalConstant ((decimal) Value, Location);
414
415                         return null;
416                 }
417
418         }
419
420         public class CharConstant : Constant {
421                 public readonly char Value;
422
423                 public CharConstant (char v, Location loc):
424                         base (loc)
425                 {
426                         type = TypeManager.char_type;
427                         eclass = ExprClass.Value;
428                         Value = v;
429                 }
430
431                 public override void Emit (EmitContext ec)
432                 {
433                         IntLiteral.EmitInt (ec.ig, Value);
434                 }
435
436                 static public string descape (char c)
437                 {
438                         switch (c){
439                         case '\a':
440                                 return "\\a"; 
441                         case '\b':
442                                 return "\\b"; 
443                         case '\n':
444                                 return "\\n"; 
445                         case '\t':
446                                 return "\\t"; 
447                         case '\v':
448                                 return "\\v"; 
449                         case '\r':
450                                 return "\\r"; 
451                         case '\\':
452                                 return "\\\\";
453                         case '\f':
454                                 return "\\f"; 
455                         case '\0':
456                                 return "\\0"; 
457                         case '"':
458                                 return "\\\""; 
459                         case '\'':
460                                 return "\\\'"; 
461                         }
462                         return c.ToString ();
463                 }
464
465                 public override string AsString ()
466                 {
467                         return "\"" + descape (Value) + "\"";
468                 }
469
470                 public override object GetValue ()
471                 {
472                         return Value;
473                 }
474
475                 public override Constant Increment ()
476                 {
477                         return new CharConstant (checked ((char)(Value + 1)), loc);
478                 }
479                 
480                 public override bool IsDefaultValue {
481                         get {
482                                 return Value == 0;
483                         }
484                 }
485
486                 public override bool IsNegative {
487                         get {
488                                 return false;
489                         }
490                 }
491
492                 public override bool IsZeroInteger {
493                         get { return Value == '\0'; }
494                 }
495
496                 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
497                 {
498                         if (target_type == TypeManager.byte_type) {
499                                 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
500                                 return new ByteConstant ((byte) Value, Location);
501                         }
502                         if (target_type == TypeManager.sbyte_type) {
503                                 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
504                                 return new SByteConstant ((sbyte) Value, Location);
505                         }
506                         if (target_type == TypeManager.short_type) {
507                                 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
508                                 return new ShortConstant ((short) Value, Location);
509                         }
510                         if (target_type == TypeManager.int32_type)
511                                 return new IntConstant ((int) Value, Location);
512                         if (target_type == TypeManager.uint32_type)
513                                 return new UIntConstant ((uint) Value, Location);
514                         if (target_type == TypeManager.int64_type)
515                                 return new LongConstant ((long) Value, Location);
516                         if (target_type == TypeManager.uint64_type)
517                                 return new ULongConstant ((ulong) Value, Location);
518                         if (target_type == TypeManager.float_type)
519                                 return new FloatConstant ((float) Value, Location);
520                         if (target_type == TypeManager.double_type)
521                                 return new DoubleConstant ((double) Value, Location);
522                         if (target_type == TypeManager.decimal_type)
523                                 return new DecimalConstant ((decimal) Value, Location);
524
525                         return null;
526                 }
527
528         }
529
530         public class SByteConstant : IntegralConstant {
531                 public readonly sbyte Value;
532
533                 public SByteConstant (sbyte v, Location loc):
534                         base (loc)
535                 {
536                         type = TypeManager.sbyte_type;
537                         eclass = ExprClass.Value;
538                         Value = v;
539                 }
540
541                 public override void Emit (EmitContext ec)
542                 {
543                         IntLiteral.EmitInt (ec.ig, Value);
544                 }
545
546                 public override string AsString ()
547                 {
548                         return Value.ToString ();
549                 }
550
551                 public override object GetValue ()
552                 {
553                         return Value;
554                 }
555
556                 public override Constant Increment ()
557                 {
558                     return new SByteConstant (checked((sbyte)(Value + 1)), loc);
559                 }
560
561                 public override bool IsDefaultValue {
562                         get {
563                                 return Value == 0;
564                         }
565                 }
566
567                 public override bool IsNegative {
568                         get {
569                                 return Value < 0;
570                         }
571                 }
572                 
573                 public override bool IsZeroInteger {
574                         get { return Value == 0; }
575                 }
576
577                 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
578                 {
579                         if (target_type == TypeManager.byte_type) {
580                                 CheckUnsigned (inCheckedContext, Value);
581                                 return new ByteConstant ((byte) Value, Location);
582                         }
583                         if (target_type == TypeManager.short_type)
584                                 return new ShortConstant ((short) Value, Location);
585                         if (target_type == TypeManager.ushort_type) {
586                                 CheckUnsigned (inCheckedContext, Value);
587                                 return new UShortConstant ((ushort) Value, Location);
588                         } if (target_type == TypeManager.int32_type)
589                                   return new IntConstant ((int) Value, Location);
590                         if (target_type == TypeManager.uint32_type) {
591                                 CheckUnsigned (inCheckedContext, Value);
592                                 return new UIntConstant ((uint) Value, Location);
593                         } if (target_type == TypeManager.int64_type)
594                                   return new LongConstant ((long) Value, Location);
595                         if (target_type == TypeManager.uint64_type) {
596                                 CheckUnsigned (inCheckedContext, Value);
597                                 return new ULongConstant ((ulong) Value, Location);
598                         }
599                         if (target_type == TypeManager.float_type)
600                                 return new FloatConstant ((float) Value, Location);
601                         if (target_type == TypeManager.double_type)
602                                 return new DoubleConstant ((double) Value, Location);
603                         if (target_type == TypeManager.char_type) {
604                                 CheckUnsigned (inCheckedContext, Value);
605                                 return new CharConstant ((char) Value, Location);
606                         }
607                         if (target_type == TypeManager.decimal_type)
608                                 return new DecimalConstant ((decimal) Value, Location);
609
610                         return null;
611                 }
612
613         }
614
615         public class ShortConstant : IntegralConstant {
616                 public readonly short Value;
617
618                 public ShortConstant (short v, Location loc):
619                         base (loc)
620                 {
621                         type = TypeManager.short_type;
622                         eclass = ExprClass.Value;
623                         Value = v;
624                 }
625
626                 public override void Emit (EmitContext ec)
627                 {
628                         IntLiteral.EmitInt (ec.ig, Value);
629                 }
630
631                 public override string AsString ()
632                 {
633                         return Value.ToString ();
634                 }
635
636                 public override object GetValue ()
637                 {
638                         return Value;
639                 }
640
641                 public override Constant Increment ()
642                 {
643                         return new ShortConstant (checked((short)(Value + 1)), loc);
644                 }
645
646                 public override bool IsDefaultValue {
647                         get {
648                                 return Value == 0;
649                         }
650                 }
651                 
652                 public override bool IsZeroInteger {
653                         get { return Value == 0; }
654                 }
655
656                 public override bool IsNegative {
657                         get {
658                                 return Value < 0;
659                         }
660                 }
661
662                 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
663                 {
664                         if (target_type == TypeManager.byte_type) {
665                                 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
666                                 return new ByteConstant ((byte) Value, Location);
667                         }
668                         if (target_type == TypeManager.sbyte_type) {
669                                 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
670                                 return new SByteConstant ((sbyte) Value, Location);
671                         }
672                         if (target_type == TypeManager.ushort_type) {
673                                 CheckUnsigned (inCheckedContext, Value);
674                                 return new UShortConstant ((ushort) Value, Location);
675                         }
676                         if (target_type == TypeManager.int32_type)
677                                 return new IntConstant ((int) Value, Location);
678                         if (target_type == TypeManager.uint32_type) {
679                                 CheckUnsigned (inCheckedContext, Value);
680                                 return new UIntConstant ((uint) Value, Location);
681                         }
682                         if (target_type == TypeManager.int64_type)
683                                 return new LongConstant ((long) Value, Location);
684                         if (target_type == TypeManager.uint64_type) {
685                                 CheckUnsigned (inCheckedContext, Value);
686                                 return new ULongConstant ((ulong) Value, Location);
687                         }
688                         if (target_type == TypeManager.float_type)
689                                 return new FloatConstant ((float) Value, Location);
690                         if (target_type == TypeManager.double_type)
691                                 return new DoubleConstant ((double) Value, Location);
692                         if (target_type == TypeManager.char_type) {
693                                 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
694                                 return new CharConstant ((char) Value, Location);
695                         }
696                         if (target_type == TypeManager.decimal_type)
697                                 return new DecimalConstant ((decimal) Value, Location);
698
699                         return null;
700                 }
701
702         }
703
704         public class UShortConstant : IntegralConstant {
705                 public readonly ushort Value;
706
707                 public UShortConstant (ushort v, Location loc):
708                         base (loc)
709                 {
710                         type = TypeManager.ushort_type;
711                         eclass = ExprClass.Value;
712                         Value = v;
713                 }
714
715                 public override void Emit (EmitContext ec)
716                 {
717                         IntLiteral.EmitInt (ec.ig, Value);
718                 }
719
720                 public override string AsString ()
721                 {
722                         return Value.ToString ();
723                 }
724
725                 public override object GetValue ()
726                 {
727                         return Value;
728                 }
729         
730                 public override Constant Increment ()
731                 {
732                         return new UShortConstant (checked((ushort)(Value + 1)), loc);
733                 }
734
735                 public override bool IsDefaultValue {
736                         get {
737                                 return Value == 0;
738                         }
739                 }
740
741                 public override bool IsNegative {
742                         get {
743                                 return false;
744                         }
745                 }
746         
747                 public override bool IsZeroInteger {
748                         get { return Value == 0; }
749                 }
750
751                 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
752                 {
753                         if (target_type == TypeManager.byte_type) {
754                                 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
755                                 return new ByteConstant ((byte) Value, Location);
756                         }
757                         if (target_type == TypeManager.sbyte_type) {
758                                 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
759                                 return new SByteConstant ((sbyte) Value, Location);
760                         }
761                         if (target_type == TypeManager.short_type) {
762                                 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
763                                 return new ShortConstant ((short) Value, Location);
764                         }
765                         if (target_type == TypeManager.int32_type)
766                                 return new IntConstant ((int) Value, Location);
767                         if (target_type == TypeManager.uint32_type)
768                                 return new UIntConstant ((uint) Value, Location);
769                         if (target_type == TypeManager.int64_type)
770                                 return new LongConstant ((long) Value, Location);
771                         if (target_type == TypeManager.uint64_type)
772                                 return new ULongConstant ((ulong) Value, Location);
773                         if (target_type == TypeManager.float_type)
774                                 return new FloatConstant ((float) Value, Location);
775                         if (target_type == TypeManager.double_type)
776                                 return new DoubleConstant ((double) Value, Location);
777                         if (target_type == TypeManager.char_type) {
778                                 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
779                                 return new CharConstant ((char) Value, Location);
780                         }
781                         if (target_type == TypeManager.decimal_type)
782                                 return new DecimalConstant ((decimal) Value, Location);
783
784                         return null;
785                 }
786         }
787
788         public class IntConstant : IntegralConstant {
789                 public readonly int Value;
790
791                 public IntConstant (int v, Location loc):
792                         base (loc)
793                 {
794                         type = TypeManager.int32_type;
795                         eclass = ExprClass.Value;
796                         Value = v;
797                 }
798
799                 static public void EmitInt (ILGenerator ig, int i)
800                 {
801                         switch (i){
802                         case -1:
803                                 ig.Emit (OpCodes.Ldc_I4_M1);
804                                 break;
805                                 
806                         case 0:
807                                 ig.Emit (OpCodes.Ldc_I4_0);
808                                 break;
809                                 
810                         case 1:
811                                 ig.Emit (OpCodes.Ldc_I4_1);
812                                 break;
813                                 
814                         case 2:
815                                 ig.Emit (OpCodes.Ldc_I4_2);
816                                 break;
817                                 
818                         case 3:
819                                 ig.Emit (OpCodes.Ldc_I4_3);
820                                 break;
821                                 
822                         case 4:
823                                 ig.Emit (OpCodes.Ldc_I4_4);
824                                 break;
825                                 
826                         case 5:
827                                 ig.Emit (OpCodes.Ldc_I4_5);
828                                 break;
829                                 
830                         case 6:
831                                 ig.Emit (OpCodes.Ldc_I4_6);
832                                 break;
833                                 
834                         case 7:
835                                 ig.Emit (OpCodes.Ldc_I4_7);
836                                 break;
837                                 
838                         case 8:
839                                 ig.Emit (OpCodes.Ldc_I4_8);
840                                 break;
841
842                         default:
843                                 if (i >= -128 && i <= 127){
844                                         ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
845                                 } else
846                                         ig.Emit (OpCodes.Ldc_I4, i);
847                                 break;
848                         }
849                 }
850
851                 public override void Emit (EmitContext ec)
852                 {
853                         EmitInt (ec.ig, Value);
854                 }
855
856                 public override string AsString ()
857                 {
858                         return Value.ToString ();
859                 }
860
861                 public override object GetValue ()
862                 {
863                         return Value;
864                 }
865
866                 public override Constant Increment ()
867                 {
868                         return new IntConstant (checked(Value + 1), loc);
869                 }
870
871                 public override bool IsDefaultValue {
872                         get {
873                                 return Value == 0;
874                         }
875                 }
876                 
877                 public override bool IsNegative {
878                         get {
879                                 return Value < 0;
880                         }
881                 }
882
883                 public override bool IsZeroInteger {
884                         get { return Value == 0; }
885                 }
886
887                 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
888                 {
889                         if (target_type == TypeManager.byte_type) {
890                                 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
891                                 return new ByteConstant ((byte) Value, Location);
892                         }
893                         if (target_type == TypeManager.sbyte_type) {
894                                 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
895                                 return new SByteConstant ((sbyte) Value, Location);
896                         }
897                         if (target_type == TypeManager.short_type) {
898                                 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
899                                 return new ShortConstant ((short) Value, Location);
900                         }
901                         if (target_type == TypeManager.ushort_type) {
902                                 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
903                                 return new UShortConstant ((ushort) Value, Location);
904                         }
905                         if (target_type == TypeManager.uint32_type) {
906                                 CheckRange (inCheckedContext, Value, UInt32.MinValue, UInt32.MaxValue);
907                                 return new UIntConstant ((uint) Value, Location);
908                         }
909                         if (target_type == TypeManager.int64_type)
910                                 return new LongConstant ((long) Value, Location);
911                         if (target_type == TypeManager.uint64_type) {
912                                 CheckUnsigned (inCheckedContext, Value);
913                                 return new ULongConstant ((ulong) Value, Location);
914                         }
915                         if (target_type == TypeManager.float_type)
916                                 return new FloatConstant ((float) Value, Location);
917                         if (target_type == TypeManager.double_type)
918                                 return new DoubleConstant ((double) Value, Location);
919                         if (target_type == TypeManager.char_type) {
920                                 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
921                                 return new CharConstant ((char) Value, Location);
922                         }
923                         if (target_type == TypeManager.decimal_type)
924                                 return new DecimalConstant ((decimal) Value, Location);
925
926                         return null;
927                 }
928         }
929
930         public class UIntConstant : IntegralConstant {
931                 public readonly uint Value;
932
933                 public UIntConstant (uint v, Location loc):
934                         base (loc)
935                 {
936                         type = TypeManager.uint32_type;
937                         eclass = ExprClass.Value;
938                         Value = v;
939                 }
940
941                 public override void Emit (EmitContext ec)
942                 {
943                         IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
944                 }
945
946                 public override string AsString ()
947                 {
948                         return Value.ToString ();
949                 }
950
951                 public override object GetValue ()
952                 {
953                         return Value;
954                 }
955
956                 public override Constant Increment ()
957                 {
958                         return new UIntConstant (checked(Value + 1), loc);
959                 }
960         
961                 public override bool IsDefaultValue {
962                         get {
963                                 return Value == 0;
964                         }
965                 }
966
967                 public override bool IsNegative {
968                         get {
969                                 return false;
970                         }
971                 }
972
973                 public override bool IsZeroInteger {
974                         get { return Value == 0; }
975                 }
976
977                 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
978                 {
979                         if (target_type == TypeManager.byte_type) {
980                                 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
981                                 return new ByteConstant ((byte) Value, Location);
982                         }
983                         if (target_type == TypeManager.sbyte_type) {
984                                 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
985                                 return new SByteConstant ((sbyte) Value, Location);
986                         }
987                         if (target_type == TypeManager.short_type) {
988                                 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
989                                 return new ShortConstant ((short) Value, Location);
990                         }
991                         if (target_type == TypeManager.ushort_type) {
992                                 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
993                                 return new UShortConstant ((ushort) Value, Location);
994                         }
995                         if (target_type == TypeManager.int32_type) {
996                                 CheckRange (inCheckedContext, Value, Int32.MinValue, Int32.MaxValue);
997                                 return new IntConstant ((int) Value, Location);
998                         }
999                         if (target_type == TypeManager.int64_type)
1000                                 return new LongConstant ((long) Value, Location);
1001                         if (target_type == TypeManager.uint64_type)
1002                                 return new ULongConstant ((ulong) Value, Location);
1003                         if (target_type == TypeManager.float_type)
1004                                 return new FloatConstant ((float) Value, Location);
1005                         if (target_type == TypeManager.double_type)
1006                                 return new DoubleConstant ((double) Value, Location);
1007                         if (target_type == TypeManager.char_type) {
1008                                 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1009                                 return new CharConstant ((char) Value, Location);
1010                         }
1011                         if (target_type == TypeManager.decimal_type)
1012                                 return new DecimalConstant ((decimal) Value, Location);
1013
1014                         return null;
1015                 }
1016
1017         }
1018
1019         public class LongConstant : IntegralConstant {
1020                 public readonly long Value;
1021
1022                 public LongConstant (long v, Location loc):
1023                         base (loc)
1024                 {
1025                         type = TypeManager.int64_type;
1026                         eclass = ExprClass.Value;
1027                         Value = v;
1028                 }
1029
1030                 public override void Emit (EmitContext ec)
1031                 {
1032                         EmitLong (ec.ig, Value);
1033                 }
1034
1035                 static public void EmitLong (ILGenerator ig, long l)
1036                 {
1037                         if (l >= int.MinValue && l <= int.MaxValue) {
1038                                 IntLiteral.EmitInt (ig, unchecked ((int) l));
1039                                 ig.Emit (OpCodes.Conv_I8);
1040                                 return;
1041                         }
1042                         ig.Emit (OpCodes.Ldc_I8, l);
1043                 }
1044
1045                 public override string AsString ()
1046                 {
1047                         return Value.ToString ();
1048                 }
1049
1050                 public override object GetValue ()
1051                 {
1052                         return Value;
1053                 }
1054
1055                 public override Constant Increment ()
1056                 {
1057                         return new LongConstant (checked(Value + 1), loc);
1058                 }
1059                 
1060                 public override bool IsDefaultValue {
1061                         get {
1062                                 return Value == 0;
1063                         }
1064                 }
1065
1066                 public override bool IsNegative {
1067                         get {
1068                                 return Value < 0;
1069                         }
1070                 }
1071
1072                 public override bool IsZeroInteger {
1073                         get { return Value == 0; }
1074                 }
1075
1076                 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
1077                 {
1078                         if (target_type == TypeManager.byte_type) {
1079                                 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1080                                 return new ByteConstant ((byte) Value, Location);
1081                         }
1082                         if (target_type == TypeManager.sbyte_type) {
1083                                 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1084                                 return new SByteConstant ((sbyte) Value, Location);
1085                         }
1086                         if (target_type == TypeManager.short_type) {
1087                                 CheckRange (inCheckedContext, Value, Int16.MinValue, Int16.MaxValue);
1088                                 return new ShortConstant ((short) Value, Location);
1089                         }
1090                         if (target_type == TypeManager.ushort_type) {
1091                                 CheckRange (inCheckedContext, Value, UInt16.MinValue, UInt16.MaxValue);
1092                                 return new UShortConstant ((ushort) Value, Location);
1093                         }
1094                         if (target_type == TypeManager.int32_type) {
1095                                 CheckRange (inCheckedContext, Value, Int32.MinValue, Int32.MaxValue);
1096                                 return new IntConstant ((int) Value, Location);
1097                         }
1098                         if (target_type == TypeManager.uint32_type) {
1099                                 CheckRange (inCheckedContext, Value, UInt32.MinValue, UInt32.MaxValue);
1100                                 return new UIntConstant ((uint) Value, Location);
1101                         }
1102                         if (target_type == TypeManager.uint64_type) {
1103                                 CheckUnsigned (inCheckedContext, Value);
1104                                 return new ULongConstant ((ulong) Value, Location);
1105                         }
1106                         if (target_type == TypeManager.float_type)
1107                                 return new FloatConstant ((float) Value, Location);
1108                         if (target_type == TypeManager.double_type)
1109                                 return new DoubleConstant ((double) Value, Location);
1110                         if (target_type == TypeManager.char_type) {
1111                                 CheckRange (inCheckedContext, Value, Char.MinValue, Char.MaxValue);
1112                                 return new CharConstant ((char) Value, Location);
1113                         }
1114                         if (target_type == TypeManager.decimal_type)
1115                                 return new DecimalConstant ((decimal) Value, Location);
1116
1117                         return null;
1118                 }
1119
1120         }
1121
1122         public class ULongConstant : IntegralConstant {
1123                 public readonly ulong Value;
1124
1125                 public ULongConstant (ulong v, Location loc):
1126                         base (loc)
1127                 {
1128                         type = TypeManager.uint64_type;
1129                         eclass = ExprClass.Value;
1130                         Value = v;
1131                 }
1132
1133                 public override void Emit (EmitContext ec)
1134                 {
1135                         ILGenerator ig = ec.ig;
1136
1137                         LongLiteral.EmitLong (ig, unchecked ((long) Value));
1138                 }
1139
1140                 public override string AsString ()
1141                 {
1142                         return Value.ToString ();
1143                 }
1144
1145                 public override object GetValue ()
1146                 {
1147                         return Value;
1148                 }
1149
1150                 public override Constant Increment ()
1151                 {
1152                         return new ULongConstant (checked(Value + 1), loc);
1153                 }
1154
1155                 public override bool IsDefaultValue {
1156                         get {
1157                                 return Value == 0;
1158                         }
1159                 }
1160
1161                 public override bool IsNegative {
1162                         get {
1163                                 return false;
1164                         }
1165                 }
1166
1167                 public override bool IsZeroInteger {
1168                         get { return Value == 0; }
1169                 }
1170
1171                 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
1172                 {
1173                         if (target_type == TypeManager.byte_type) {
1174                                 CheckRange (inCheckedContext, Value, Byte.MaxValue);
1175                                 return new ByteConstant ((byte) Value, Location);
1176                         }
1177                         if (target_type == TypeManager.sbyte_type) {
1178                                 CheckRange (inCheckedContext, Value, (ulong) SByte.MaxValue);
1179                                 return new SByteConstant ((sbyte) Value, Location);
1180                         }
1181                         if (target_type == TypeManager.short_type) {
1182                                 CheckRange (inCheckedContext, Value, (ulong) Int16.MaxValue);
1183                                 return new ShortConstant ((short) Value, Location);
1184                         }
1185                         if (target_type == TypeManager.ushort_type) {
1186                                 CheckRange (inCheckedContext, Value, UInt16.MaxValue);
1187                                 return new UShortConstant ((ushort) Value, Location);
1188                         }
1189                         if (target_type == TypeManager.int32_type) {
1190                                 CheckRange (inCheckedContext, Value, Int32.MaxValue);
1191                                 return new IntConstant ((int) Value, Location);
1192                         }
1193                         if (target_type == TypeManager.uint32_type) {
1194                                 CheckRange (inCheckedContext, Value, UInt32.MaxValue);
1195                                 return new UIntConstant ((uint) Value, Location);
1196                         }
1197                         if (target_type == TypeManager.int64_type) {
1198                                 CheckRange (inCheckedContext, Value, (ulong) Int64.MaxValue);
1199                                 return new LongConstant ((long) Value, Location);
1200                         }
1201                         if (target_type == TypeManager.float_type)
1202                                 return new FloatConstant ((float) Value, Location);
1203                         if (target_type == TypeManager.double_type)
1204                                 return new DoubleConstant ((double) Value, Location);
1205                         if (target_type == TypeManager.char_type) {
1206                                 CheckRange (inCheckedContext, Value, Char.MaxValue);
1207                                 return new CharConstant ((char) Value, Location);
1208                         }
1209                         if (target_type == TypeManager.decimal_type)
1210                                 return new DecimalConstant ((decimal) Value, Location);
1211
1212                         return null;
1213                 }
1214
1215         }
1216
1217         public class FloatConstant : Constant {
1218                 public float Value;
1219
1220                 public FloatConstant (float v, Location loc):
1221                         base (loc)
1222                 {
1223                         type = TypeManager.float_type;
1224                         eclass = ExprClass.Value;
1225                         Value = v;
1226                 }
1227
1228                 public override void Emit (EmitContext ec)
1229                 {
1230                         ec.ig.Emit (OpCodes.Ldc_R4, Value);
1231                 }
1232
1233                 public override string AsString ()
1234                 {
1235                         return Value.ToString ();
1236                 }
1237
1238                 public override object GetValue ()
1239                 {
1240                         return Value;
1241                 }
1242
1243                 public override Constant Increment ()
1244                 {
1245                         return new FloatConstant (checked(Value + 1), loc);
1246                 }
1247
1248                 public override bool IsDefaultValue {
1249                         get {
1250                                 return Value == 0;
1251                         }
1252                 }
1253
1254                 public override bool IsNegative {
1255                         get {
1256                                 return Value < 0;
1257                         }
1258                 }
1259
1260                 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
1261                 {
1262                         if (target_type == TypeManager.byte_type) {
1263                                 CheckRange (inCheckedContext, Value, byte.MinValue, byte.MaxValue);
1264                                 return new ByteConstant ((byte) Value, Location);
1265                         }
1266                         if (target_type == TypeManager.sbyte_type) {
1267                                 CheckRange (inCheckedContext, Value,  sbyte.MinValue, sbyte.MaxValue);
1268                                 return new SByteConstant ((sbyte) Value, Location);
1269                         }
1270                         if (target_type == TypeManager.short_type) {
1271                                 CheckRange (inCheckedContext, Value, short.MinValue, short.MaxValue);
1272                                 return new ShortConstant ((short) Value, Location);
1273                         }
1274                         if (target_type == TypeManager.ushort_type) {
1275                                 CheckRange (inCheckedContext, Value, ushort.MinValue, ushort.MaxValue);
1276                                 return new UShortConstant ((ushort) Value, Location);
1277                         }
1278                         if (target_type == TypeManager.int32_type) {
1279                                 CheckRange (inCheckedContext, Value, int.MinValue, int.MaxValue);
1280                                 return new IntConstant ((int) Value, Location);
1281                         }
1282                         if (target_type == TypeManager.uint32_type) {
1283                                 CheckRange (inCheckedContext, Value, uint.MinValue, uint.MaxValue);
1284                                 return new UIntConstant ((uint) Value, Location);
1285                         }
1286                         if (target_type == TypeManager.int64_type) {
1287                                 CheckRange (inCheckedContext, Value, long.MinValue, long.MaxValue);
1288                                 return new LongConstant ((long) Value, Location);
1289                         }
1290                         if (target_type == TypeManager.uint64_type) {
1291                                 CheckRange (inCheckedContext, Value, ulong.MinValue, ulong.MaxValue);
1292                                 return new ULongConstant ((ulong) Value, Location);
1293                         }
1294                         if (target_type == TypeManager.double_type)
1295                                 return new DoubleConstant ((double) Value, Location);
1296                         if (target_type == TypeManager.char_type) {
1297                                 CheckRange (inCheckedContext, Value, char.MinValue, char.MaxValue);
1298                                 return new CharConstant ((char) Value, Location);
1299                         }
1300                         if (target_type == TypeManager.decimal_type)
1301                                 return new DecimalConstant ((decimal) Value, Location);
1302
1303                         return null;
1304                 }
1305
1306         }
1307
1308         public class DoubleConstant : Constant {
1309                 public double Value;
1310
1311                 public DoubleConstant (double v, Location loc):
1312                         base (loc)
1313                 {
1314                         type = TypeManager.double_type;
1315                         eclass = ExprClass.Value;
1316                         Value = v;
1317                 }
1318
1319                 public override void Emit (EmitContext ec)
1320                 {
1321                         ec.ig.Emit (OpCodes.Ldc_R8, Value);
1322                 }
1323
1324                 public override string AsString ()
1325                 {
1326                         return Value.ToString ();
1327                 }
1328
1329                 public override object GetValue ()
1330                 {
1331                         return Value;
1332                 }
1333
1334                 public override Constant Increment ()
1335                 {
1336                         return new DoubleConstant (checked(Value + 1), loc);
1337                 }
1338
1339                 public override bool IsDefaultValue {
1340                         get {
1341                                 return Value == 0;
1342                         }
1343                 }
1344
1345                 public override bool IsNegative {
1346                         get {
1347                                 return Value < 0;
1348                         }
1349                 }
1350
1351                 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
1352                 {
1353                         if (target_type == TypeManager.byte_type) {
1354                                 CheckRange (inCheckedContext, Value, Byte.MinValue, Byte.MaxValue);
1355                                 return new ByteConstant ((byte) Value, Location);
1356                         }
1357                         if (target_type == TypeManager.sbyte_type) {
1358                                 CheckRange (inCheckedContext, Value, SByte.MinValue, SByte.MaxValue);
1359                                 return new SByteConstant ((sbyte) Value, Location);
1360                         }
1361                         if (target_type == TypeManager.short_type) {
1362                                 CheckRange (inCheckedContext, Value, short.MinValue, short.MaxValue);
1363                                 return new ShortConstant ((short) Value, Location);
1364                         }
1365                         if (target_type == TypeManager.ushort_type) {
1366                                 CheckRange (inCheckedContext, Value, ushort.MinValue, ushort.MaxValue);
1367                                 return new UShortConstant ((ushort) Value, Location);
1368                         }
1369                         if (target_type == TypeManager.int32_type) {
1370                                 CheckRange (inCheckedContext, Value, int.MinValue, int.MaxValue);
1371                                 return new IntConstant ((int) Value, Location);
1372                         }
1373                         if (target_type == TypeManager.uint32_type) {
1374                                 CheckRange (inCheckedContext, Value, uint.MinValue, uint.MaxValue);
1375                                 return new UIntConstant ((uint) Value, Location);
1376                         }
1377                         if (target_type == TypeManager.int64_type) {
1378                                 CheckRange (inCheckedContext, Value, long.MinValue, long.MaxValue);
1379                                 return new LongConstant ((long) Value, Location);
1380                         }
1381                         if (target_type == TypeManager.uint64_type) {
1382                                 CheckRange (inCheckedContext, Value, ulong.MinValue, ulong.MaxValue);
1383                                 return new ULongConstant ((ulong) Value, Location);
1384                         }
1385                         if (target_type == TypeManager.float_type)
1386                                 return new FloatConstant ((float) Value, Location);
1387                         if (target_type == TypeManager.char_type) {
1388                                 CheckRange (inCheckedContext, Value, char.MinValue, char.MaxValue);
1389                                 return new CharConstant ((char) Value, Location);
1390                         }
1391                         if (target_type == TypeManager.decimal_type)
1392                                 return new DecimalConstant ((decimal) Value, Location);
1393
1394                         return null;
1395                 }
1396
1397         }
1398
1399         public class DecimalConstant : Constant {
1400                 public readonly decimal Value;
1401
1402                 public DecimalConstant (decimal d, Location loc):
1403                         base (loc)
1404                 {
1405                         type = TypeManager.decimal_type;
1406                         eclass = ExprClass.Value;
1407                         Value = d;
1408                 }
1409
1410                 override public string AsString ()
1411                 {
1412                         return Value.ToString ();
1413                 }
1414
1415                 public override object GetValue ()
1416                 {
1417                         return (object) Value;
1418                 }
1419
1420                 public override void Emit (EmitContext ec)
1421                 {
1422                         ILGenerator ig = ec.ig;
1423
1424                         int [] words = Decimal.GetBits (Value);
1425                         int power = (words [3] >> 16) & 0xff;
1426
1427                         if (power == 0 && Value <= int.MaxValue && Value >= int.MinValue)
1428                         {
1429                                 IntConstant.EmitInt (ig, (int)Value);
1430                                 ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_int_arg);
1431                                 return;
1432                         }
1433
1434                         
1435                         //
1436                         // FIXME: we could optimize this, and call a better 
1437                         // constructor
1438                         //
1439
1440                         IntConstant.EmitInt (ig, words [0]);
1441                         IntConstant.EmitInt (ig, words [1]);
1442                         IntConstant.EmitInt (ig, words [2]);
1443
1444                         // sign
1445                         IntConstant.EmitInt (ig, words [3] >> 31);
1446
1447                         // power
1448                         IntConstant.EmitInt (ig, power);
1449
1450                         ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
1451                 }
1452
1453                 public override Constant Increment ()
1454                 {
1455                         return new DecimalConstant (checked (Value + 1), loc);
1456                 }
1457
1458                 public override bool IsDefaultValue {
1459                         get {
1460                                 return Value == 0;
1461                         }
1462                 }
1463
1464                 public override bool IsNegative {
1465                         get {
1466                                 return Value < 0;
1467                         }
1468                 }
1469
1470                 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
1471                 {
1472                         if (target_type == TypeManager.sbyte_type)
1473                                 return new SByteConstant ((sbyte)Value, loc);
1474                         if (target_type == TypeManager.byte_type)
1475                                 return new ByteConstant ((byte)Value, loc);
1476                         if (target_type == TypeManager.short_type)
1477                                 return new ShortConstant ((short)Value, loc);
1478                         if (target_type == TypeManager.ushort_type)
1479                                 return new UShortConstant ((ushort)Value, loc);
1480                         if (target_type == TypeManager.int32_type)
1481                                 return new IntConstant ((int)Value, loc);
1482                         if (target_type == TypeManager.uint32_type)
1483                                 return new UIntConstant ((uint)Value, loc);
1484                         if (target_type == TypeManager.int64_type)
1485                                 return new LongConstant ((long)Value, loc);
1486                         if (target_type == TypeManager.uint64_type)
1487                                 return new ULongConstant ((ulong)Value, loc);
1488                         if (target_type == TypeManager.char_type)
1489                                 return new CharConstant ((char)Value, loc);
1490                         if (target_type == TypeManager.float_type)
1491                                 return new FloatConstant ((float)Value, loc);
1492                         if (target_type == TypeManager.double_type)
1493                                 return new DoubleConstant ((double)Value, loc);
1494
1495                         return null;
1496                 }
1497
1498         }
1499
1500         public class StringConstant : Constant {
1501                 public readonly string Value;
1502
1503                 public StringConstant (string s, Location loc):
1504                         base (loc)
1505                 {
1506                         type = TypeManager.string_type;
1507                         eclass = ExprClass.Value;
1508                         Value = s;
1509                 }
1510
1511                 // FIXME: Escape the string.
1512                 override public string AsString ()
1513                 {
1514                         return "\"" + Value + "\"";
1515                 }
1516
1517                 public override object GetValue ()
1518                 {
1519                         return Value;
1520                 }
1521                 
1522                 public override void Emit (EmitContext ec)
1523                 {
1524                         if (Value == null)
1525                                 ec.ig.Emit (OpCodes.Ldnull);
1526                         else
1527                                 ec.ig.Emit (OpCodes.Ldstr, Value);
1528                 }
1529
1530                 public override Constant Increment ()
1531                 {
1532                         throw new NotSupportedException ();
1533                 }
1534
1535                 public override bool IsDefaultValue {
1536                         get {
1537                                 return Value == null;
1538                         }
1539                 }
1540
1541                 public override bool IsNegative {
1542                         get {
1543                                 return false;
1544                         }
1545                 }
1546
1547                 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
1548                 {
1549                         return null;
1550                 }
1551         }
1552
1553 }
1554
1555