2004-10-14 Umadevi S <sumadevi@novell.com>
[mono.git] / mcs / gmcs / cfold.cs
1 //
2 // cfold.cs: Constant Folding
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2002, 2003 Ximian, Inc.
8 //
9
10 using System;
11
12 namespace Mono.CSharp {
13
14         public class ConstantFold {
15
16                 //
17                 // Performs the numeric promotions on the left and right expresions
18                 // and desposits the results on `lc' and `rc'.
19                 //
20                 // On success, the types of `lc' and `rc' on output will always match,
21                 // and the pair will be one of:
22                 //
23                 //   (double, double)
24                 //   (float, float)
25                 //   (ulong, ulong)
26                 //   (long, long)
27                 //   (uint, uint)
28                 //   (int, int)
29                 //   (short, short)   (Happens with enumerations with underlying short type)
30                 //   (ushort, ushort) (Happens with enumerations with underlying short type)
31                 //
32                 static void DoConstantNumericPromotions (EmitContext ec, Binary.Operator oper,
33                                                          ref Constant left, ref Constant right,
34                                                          Location loc)
35                 {
36                         if (left is DoubleConstant || right is DoubleConstant){
37                                 //
38                                 // If either side is a double, convert the other to a double
39                                 //
40                                 if (!(left is DoubleConstant))
41                                         left = left.ToDouble (loc);
42
43                                 if (!(right is DoubleConstant))
44                                         right = right.ToDouble (loc);
45                                 return;
46                         } else if (left is FloatConstant || right is FloatConstant) {
47                                 //
48                                 // If either side is a float, convert the other to a float
49                                 //
50                                 if (!(left is FloatConstant))
51                                         left = left.ToFloat (loc);
52
53                                 if (!(right is FloatConstant))
54                                         right = right.ToFloat (loc);
55 ;                               return;
56                         } else if (left is ULongConstant || right is ULongConstant){
57                                 //
58                                 // If either operand is of type ulong, the other operand is
59                                 // converted to type ulong.  or an error ocurrs if the other
60                                 // operand is of type sbyte, short, int or long
61                                 //
62 #if WRONG
63                                 Constant match, other;
64 #endif
65                                         
66                                 if (left is ULongConstant){
67 #if WRONG
68                                         other = right;
69                                         match = left;
70 #endif
71                                         if (!(right is ULongConstant))
72                                                 right = right.ToULong (loc);
73                                 } else {
74 #if WRONG
75                                         other = left;
76                                         match = right;
77 #endif
78                                         left = left.ToULong (loc);
79                                 }
80
81 #if WRONG
82                                 if (other is SByteConstant || other is ShortConstant ||
83                                     other is IntConstant || other is LongConstant){
84                                         Binary.Error_OperatorAmbiguous
85                                                 (loc, oper, other.Type, match.Type);
86                                         left = null;
87                                         right = null;
88                                 }
89 #endif
90                                 return;
91                         } else if (left is LongConstant || right is LongConstant){
92                                 //
93                                 // If either operand is of type long, the other operand is converted
94                                 // to type long.
95                                 //
96                                 if (!(left is LongConstant))
97                                         left = left.ToLong (loc);
98                                 else if (!(right is LongConstant))
99                                         right = right.ToLong (loc);
100                                 return;
101                         } else if (left is UIntConstant || right is UIntConstant){
102                                 //
103                                 // If either operand is of type uint, and the other
104                                 // operand is of type sbyte, short or int, the operands are
105                                 // converted to type long.
106                                 //
107                                 Constant other;
108                                 if (left is UIntConstant)
109                                         other = right;
110                                 else
111                                         other = left;
112
113                                 // Nothing to do.
114                                 if (other is UIntConstant)
115                                         return;
116
117                                 IntConstant ic = other as IntConstant;
118                                 if (ic != null){
119                                         if (ic.Value >= 0){
120                                                 if (left == other)
121                                                         left = new UIntConstant ((uint) ic.Value);
122                                                 else
123                                                         right = new UIntConstant ((uint) ic.Value);
124                                                 return;
125                                         }
126                                 }
127                                 
128                                 if (other is SByteConstant || other is ShortConstant || ic != null){
129                                         left = left.ToLong (loc);
130                                         right = right.ToLong (loc);
131                                 } else {
132                                         left = left.ToUInt (loc);
133                                         right = left.ToUInt (loc);
134                                 }
135
136                                 return;
137                         } else if (left is EnumConstant || right is EnumConstant){
138                                 //
139                                 // If either operand is an enum constant, the other one must
140                                 // be implicitly convertable to that enum's underlying type.
141                                 //
142                                 EnumConstant match;
143                                 Constant other;
144                                 if (left is EnumConstant){
145                                         other = right;
146                                         match = (EnumConstant) left;
147                                 } else {
148                                         other = left;
149                                         match = (EnumConstant) right;
150                                 }
151
152                                 bool need_check = (other is EnumConstant) ||
153                                         ((oper != Binary.Operator.Addition) &&
154                                          (oper != Binary.Operator.Subtraction));
155
156                                 if (need_check &&
157                                     !Convert.ImplicitConversionExists (ec, match, other.Type)) {
158                                         Convert.Error_CannotImplicitConversion (loc, match.Type, other.Type);
159                                         left = null;
160                                         right = null;
161                                         return;
162                                 }
163
164                                 if (left is EnumConstant)
165                                         left = ((EnumConstant) left).Child;
166                                 if (right is EnumConstant)
167                                         right = ((EnumConstant) right).Child;
168                                 return;
169
170                         } else {
171                                 //
172                                 // Force conversions to int32
173                                 //
174                                 if (!(left is IntConstant))
175                                         left = left.ToInt (loc);
176                                 if (!(right is IntConstant))
177                                         right = right.ToInt (loc);
178                         }
179                         return;
180                 }
181
182                 static void Error_CompileTimeOverflow (Location loc)
183                 {
184                         Report.Error (220, loc, "The operation overflows at compile time in checked mode");
185                 }
186                 
187                 /// <summary>
188                 ///   Constant expression folder for binary operations.
189                 ///
190                 ///   Returns null if the expression can not be folded.
191                 /// </summary>
192                 static public Expression BinaryFold (EmitContext ec, Binary.Operator oper,
193                                                      Constant left, Constant right, Location loc)
194                 {
195                         Type lt = left.Type;
196                         Type rt = right.Type;
197                         Type result_type = null;
198                         bool bool_res;
199
200                         //
201                         // Enumerator folding
202                         //
203                         if (rt == lt && left is EnumConstant)
204                                 result_type = lt;
205
206                         //
207                         // During an enum evaluation, we need to unwrap enumerations
208                         //
209                         if (ec.InEnumContext){
210                                 if (left is EnumConstant)
211                                         left = ((EnumConstant) left).Child;
212                                 
213                                 if (right is EnumConstant)
214                                         right = ((EnumConstant) right).Child;
215                         }
216
217                         Type wrap_as;
218                         Constant result = null;
219                         switch (oper){
220                         case Binary.Operator.BitwiseOr:
221                                 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
222                                 if (left == null || right == null)
223                                         return null;
224                                 
225                                 if (left is IntConstant){
226                                         IntConstant v;
227                                         int res = ((IntConstant) left).Value | ((IntConstant) right).Value;
228                                         
229                                         v = new IntConstant (res);
230                                         if (result_type == null)
231                                                 return v;
232                                         else
233                                                 return new EnumConstant (v, result_type);
234                                 } else if (left is UIntConstant){
235                                         UIntConstant v;
236                                         uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value;
237                                         
238                                         v = new UIntConstant (res);
239                                         if (result_type == null)
240                                                 return v;
241                                         else
242                                                 return new EnumConstant (v, result_type);
243                                 } else if (left is LongConstant){
244                                         LongConstant v;
245                                         long res = ((LongConstant)left).Value | ((LongConstant)right).Value;
246                                         
247                                         v = new LongConstant (res);
248                                         if (result_type == null)
249                                                 return v;
250                                         else
251                                                 return new EnumConstant (v, result_type);
252                                 } else if (left is ULongConstant){
253                                         ULongConstant v;
254                                         ulong res = ((ULongConstant)left).Value |
255                                                 ((ULongConstant)right).Value;
256                                         
257                                         v = new ULongConstant (res);
258                                         if (result_type == null)
259                                                 return v;
260                                         else
261                                                 return new EnumConstant (v, result_type);
262                                 } else if (left is UShortConstant){
263                                         UShortConstant v;
264                                         ushort res = (ushort) (((UShortConstant)left).Value |
265                                                                ((UShortConstant)right).Value);
266                                         
267                                         v = new UShortConstant (res);
268                                         if (result_type == null)
269                                                 return v;
270                                         else
271                                                 return new EnumConstant (v, result_type);
272                                 } else if (left is ShortConstant){
273                                         ShortConstant v;
274                                         short res = (short) (((ShortConstant)left).Value |
275                                                              ((ShortConstant)right).Value);
276                                         
277                                         v = new ShortConstant (res);
278                                         if (result_type == null)
279                                                 return v;
280                                         else
281                                                 return new EnumConstant (v, result_type);
282                                 }
283                                 break;
284                                 
285                         case Binary.Operator.BitwiseAnd:
286                                 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
287                                 if (left == null || right == null)
288                                         return null;
289                                 
290                                 if (left is IntConstant){
291                                         IntConstant v;
292                                         int res = ((IntConstant) left).Value & ((IntConstant) right).Value;
293                                         
294                                         v = new IntConstant (res);
295                                         if (result_type == null)
296                                                 return v;
297                                         else
298                                                 return new EnumConstant (v, result_type);
299                                 } else if (left is UIntConstant){
300                                         UIntConstant v;
301                                         uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value;
302                                         
303                                         v = new UIntConstant (res);
304                                         if (result_type == null)
305                                                 return v;
306                                         else
307                                                 return new EnumConstant (v, result_type);
308                                 } else if (left is LongConstant){
309                                         LongConstant v;
310                                         long res = ((LongConstant)left).Value & ((LongConstant)right).Value;
311                                         
312                                         v = new LongConstant (res);
313                                         if (result_type == null)
314                                                 return v;
315                                         else
316                                                 return new EnumConstant (v, result_type);
317                                 } else if (left is ULongConstant){
318                                         ULongConstant v;
319                                         ulong res = ((ULongConstant)left).Value &
320                                                 ((ULongConstant)right).Value;
321                                         
322                                         v = new ULongConstant (res);
323                                         if (result_type == null)
324                                                 return v;
325                                         else
326                                                 return new EnumConstant (v, result_type);
327                                 } else if (left is UShortConstant){
328                                         UShortConstant v;
329                                         ushort res = (ushort) (((UShortConstant)left).Value &
330                                                                ((UShortConstant)right).Value);
331                                         
332                                         v = new UShortConstant (res);
333                                         if (result_type == null)
334                                                 return v;
335                                         else
336                                                 return new EnumConstant (v, result_type);
337                                 } else if (left is ShortConstant){
338                                         ShortConstant v;
339                                         short res = (short) (((ShortConstant)left).Value &
340                                                              ((ShortConstant)right).Value);
341                                         
342                                         v = new ShortConstant (res);
343                                         if (result_type == null)
344                                                 return v;
345                                         else
346                                                 return new EnumConstant (v, result_type);
347                                 }
348                                 break;
349
350                         case Binary.Operator.ExclusiveOr:
351                                 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
352                                 if (left == null || right == null)
353                                         return null;
354                                 
355                                 if (left is IntConstant){
356                                         IntConstant v;
357                                         int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value;
358                                         
359                                         v = new IntConstant (res);
360                                         if (result_type == null)
361                                                 return v;
362                                         else
363                                                 return new EnumConstant (v, result_type);
364                                 } else if (left is UIntConstant){
365                                         UIntConstant v;
366                                         uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value;
367                                         
368                                         v = new UIntConstant (res);
369                                         if (result_type == null)
370                                                 return v;
371                                         else
372                                                 return new EnumConstant (v, result_type);
373                                 } else if (left is LongConstant){
374                                         LongConstant v;
375                                         long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value;
376                                         
377                                         v = new LongConstant (res);
378                                         if (result_type == null)
379                                                 return v;
380                                         else
381                                                 return new EnumConstant (v, result_type);
382                                 } else if (left is ULongConstant){
383                                         ULongConstant v;
384                                         ulong res = ((ULongConstant)left).Value ^
385                                                 ((ULongConstant)right).Value;
386                                         
387                                         v = new ULongConstant (res);
388                                         if (result_type == null)
389                                                 return v;
390                                         else
391                                                 return new EnumConstant (v, result_type);
392                                 } else if (left is UShortConstant){
393                                         UShortConstant v;
394                                         ushort res = (ushort) (((UShortConstant)left).Value ^
395                                                                ((UShortConstant)right).Value);
396                                         
397                                         v = new UShortConstant (res);
398                                         if (result_type == null)
399                                                 return v;
400                                         else
401                                                 return new EnumConstant (v, result_type);
402                                 } else if (left is ShortConstant){
403                                         ShortConstant v;
404                                         short res = (short)(((ShortConstant)left).Value ^
405                                                             ((ShortConstant)right).Value);
406                                         
407                                         v = new ShortConstant (res);
408                                         if (result_type == null)
409                                                 return v;
410                                         else
411                                                 return new EnumConstant (v, result_type);
412                                 }
413                                 break;
414
415                         case Binary.Operator.Addition:
416                                 bool left_is_string = left is StringConstant;
417                                 bool right_is_string = right is StringConstant;
418
419                                 //
420                                 // If both sides are strings, then concatenate, if
421                                 // one is a string, and the other is not, then defer
422                                 // to runtime concatenation
423                                 //
424                                 wrap_as = null;
425                                 if (left_is_string || right_is_string){
426                                         if (left_is_string && right_is_string)
427                                                 return new StringConstant (
428                                                         ((StringConstant) left).Value +
429                                                         ((StringConstant) right).Value);
430                                         
431                                         return null;
432                                 }
433
434                                 //
435                                 // handle "E operator + (E x, U y)"
436                                 // handle "E operator + (Y y, E x)"
437                                 //
438                                 // note that E operator + (E x, E y) is invalid
439                                 //
440                                 if (left is EnumConstant){
441                                         if (right is EnumConstant){
442                                                 return null;
443                                         }
444                                         if (((EnumConstant) left).Child.Type != right.Type)
445                                                 return null;
446
447                                         wrap_as = left.Type;
448                                 } else if (right is EnumConstant){
449                                         if (((EnumConstant) right).Child.Type != left.Type)
450                                                 return null;
451                                         wrap_as = right.Type;
452                                 }
453
454                                 result = null;
455                                 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
456                                 if (left == null || right == null)
457                                         return null;
458
459                                 try {
460                                         if (left is DoubleConstant){
461                                                 double res;
462                                                 
463                                                 if (ec.ConstantCheckState)
464                                                         res = checked (((DoubleConstant) left).Value +
465                                                                        ((DoubleConstant) right).Value);
466                                                 else
467                                                         res = unchecked (((DoubleConstant) left).Value +
468                                                                          ((DoubleConstant) right).Value);
469                                                 
470                                                 result = new DoubleConstant (res);
471                                         } else if (left is FloatConstant){
472                                                 float res;
473                                                 
474                                                 if (ec.ConstantCheckState)
475                                                         res = checked (((FloatConstant) left).Value +
476                                                                        ((FloatConstant) right).Value);
477                                                 else
478                                                         res = unchecked (((FloatConstant) left).Value +
479                                                                          ((FloatConstant) right).Value);
480                                                 
481                                                 result = new FloatConstant (res);
482                                         } else if (left is ULongConstant){
483                                                 ulong res;
484                                                 
485                                                 if (ec.ConstantCheckState)
486                                                         res = checked (((ULongConstant) left).Value +
487                                                                        ((ULongConstant) right).Value);
488                                                 else
489                                                         res = unchecked (((ULongConstant) left).Value +
490                                                                          ((ULongConstant) right).Value);
491
492                                                 result = new ULongConstant (res);
493                                         } else if (left is LongConstant){
494                                                 long res;
495                                                 
496                                                 if (ec.ConstantCheckState)
497                                                         res = checked (((LongConstant) left).Value +
498                                                                        ((LongConstant) right).Value);
499                                                 else
500                                                         res = unchecked (((LongConstant) left).Value +
501                                                                          ((LongConstant) right).Value);
502                                                 
503                                                 result = new LongConstant (res);
504                                         } else if (left is UIntConstant){
505                                                 uint res;
506                                                 
507                                                 if (ec.ConstantCheckState)
508                                                         res = checked (((UIntConstant) left).Value +
509                                                                        ((UIntConstant) right).Value);
510                                                 else
511                                                         res = unchecked (((UIntConstant) left).Value +
512                                                                          ((UIntConstant) right).Value);
513                                                 
514                                                 result = new UIntConstant (res);
515                                         } else if (left is IntConstant){
516                                                 int res;
517
518                                                 if (ec.ConstantCheckState)
519                                                         res = checked (((IntConstant) left).Value +
520                                                                        ((IntConstant) right).Value);
521                                                 else
522                                                         res = unchecked (((IntConstant) left).Value +
523                                                                          ((IntConstant) right).Value);
524
525                                                 result = new IntConstant (res);
526                                         } else {
527                                                 throw new Exception ( "Unexepected input: " + left);
528                                         }
529                                 } catch (OverflowException){
530                                         Error_CompileTimeOverflow (loc);
531                                 }
532
533                                 if (wrap_as != null)
534                                         return new EnumConstant (result, wrap_as);
535                                 else
536                                         return result;
537
538                         case Binary.Operator.Subtraction:
539                                 //
540                                 // handle "E operator - (E x, U y)"
541                                 // handle "E operator - (Y y, E x)"
542                                 // handle "U operator - (E x, E y)"
543                                 //
544                                 wrap_as = null;
545                                 if (left is EnumConstant){
546                                         if (right is EnumConstant){
547                                                 if (left.Type == right.Type)
548                                                         wrap_as = TypeManager.EnumToUnderlying (left.Type);
549                                                 else
550                                                         return null;
551                                         }
552                                         if (((EnumConstant) left).Child.Type != right.Type)
553                                                 return null;
554
555                                         wrap_as = left.Type;
556                                 } else if (right is EnumConstant){
557                                         if (((EnumConstant) right).Child.Type != left.Type)
558                                                 return null;
559                                         wrap_as = right.Type;
560                                 }
561
562                                 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
563                                 if (left == null || right == null)
564                                         return null;
565
566                                 try {
567                                         if (left is DoubleConstant){
568                                                 double res;
569                                                 
570                                                 if (ec.ConstantCheckState)
571                                                         res = checked (((DoubleConstant) left).Value -
572                                                                        ((DoubleConstant) right).Value);
573                                                 else
574                                                         res = unchecked (((DoubleConstant) left).Value -
575                                                                          ((DoubleConstant) right).Value);
576                                                 
577                                                 result = new DoubleConstant (res);
578                                         } else if (left is FloatConstant){
579                                                 float res;
580                                                 
581                                                 if (ec.ConstantCheckState)
582                                                         res = checked (((FloatConstant) left).Value -
583                                                                        ((FloatConstant) right).Value);
584                                                 else
585                                                         res = unchecked (((FloatConstant) left).Value -
586                                                                          ((FloatConstant) right).Value);
587                                                 
588                                                 result = new FloatConstant (res);
589                                         } else if (left is ULongConstant){
590                                                 ulong res;
591                                                 
592                                                 if (ec.ConstantCheckState)
593                                                         res = checked (((ULongConstant) left).Value -
594                                                                        ((ULongConstant) right).Value);
595                                                 else
596                                                         res = unchecked (((ULongConstant) left).Value -
597                                                                          ((ULongConstant) right).Value);
598                                                 
599                                                 result = new ULongConstant (res);
600                                         } else if (left is LongConstant){
601                                                 long res;
602                                                 
603                                                 if (ec.ConstantCheckState)
604                                                         res = checked (((LongConstant) left).Value -
605                                                                        ((LongConstant) right).Value);
606                                                 else
607                                                         res = unchecked (((LongConstant) left).Value -
608                                                                          ((LongConstant) right).Value);
609                                                 
610                                                 result = new LongConstant (res);
611                                         } else if (left is UIntConstant){
612                                                 uint res;
613                                                 
614                                                 if (ec.ConstantCheckState)
615                                                         res = checked (((UIntConstant) left).Value -
616                                                                        ((UIntConstant) right).Value);
617                                                 else
618                                                         res = unchecked (((UIntConstant) left).Value -
619                                                                          ((UIntConstant) right).Value);
620                                                 
621                                                 result = new UIntConstant (res);
622                                         } else if (left is IntConstant){
623                                                 int res;
624
625                                                 if (ec.ConstantCheckState)
626                                                         res = checked (((IntConstant) left).Value -
627                                                                        ((IntConstant) right).Value);
628                                                 else
629                                                         res = unchecked (((IntConstant) left).Value -
630                                                                          ((IntConstant) right).Value);
631
632                                                 result = new IntConstant (res);
633                                         } else {
634                                                 throw new Exception ( "Unexepected input: " + left);
635                                         }
636                                 } catch (OverflowException){
637                                         Error_CompileTimeOverflow (loc);
638                                 }
639                                 if (wrap_as != null)
640                                         return new EnumConstant (result, wrap_as);
641                                 else
642                                         return result;
643                                 
644                         case Binary.Operator.Multiply:
645                                 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
646                                 if (left == null || right == null)
647                                         return null;
648
649                                 try {
650                                         if (left is DoubleConstant){
651                                                 double res;
652                                                 
653                                                 if (ec.ConstantCheckState)
654                                                         res = checked (((DoubleConstant) left).Value *
655                                                                        ((DoubleConstant) right).Value);
656                                                 else
657                                                         res = unchecked (((DoubleConstant) left).Value *
658                                                                          ((DoubleConstant) right).Value);
659                                                 
660                                                 return new DoubleConstant (res);
661                                         } else if (left is FloatConstant){
662                                                 float res;
663                                                 
664                                                 if (ec.ConstantCheckState)
665                                                         res = checked (((FloatConstant) left).Value *
666                                                                        ((FloatConstant) right).Value);
667                                                 else
668                                                         res = unchecked (((FloatConstant) left).Value *
669                                                                          ((FloatConstant) right).Value);
670                                                 
671                                                 return new FloatConstant (res);
672                                         } else if (left is ULongConstant){
673                                                 ulong res;
674                                                 
675                                                 if (ec.ConstantCheckState)
676                                                         res = checked (((ULongConstant) left).Value *
677                                                                        ((ULongConstant) right).Value);
678                                                 else
679                                                         res = unchecked (((ULongConstant) left).Value *
680                                                                          ((ULongConstant) right).Value);
681                                                 
682                                                 return new ULongConstant (res);
683                                         } else if (left is LongConstant){
684                                                 long res;
685                                                 
686                                                 if (ec.ConstantCheckState)
687                                                         res = checked (((LongConstant) left).Value *
688                                                                        ((LongConstant) right).Value);
689                                                 else
690                                                         res = unchecked (((LongConstant) left).Value *
691                                                                          ((LongConstant) right).Value);
692                                                 
693                                                 return new LongConstant (res);
694                                         } else if (left is UIntConstant){
695                                                 uint res;
696                                                 
697                                                 if (ec.ConstantCheckState)
698                                                         res = checked (((UIntConstant) left).Value *
699                                                                        ((UIntConstant) right).Value);
700                                                 else
701                                                         res = unchecked (((UIntConstant) left).Value *
702                                                                          ((UIntConstant) right).Value);
703                                                 
704                                                 return new UIntConstant (res);
705                                         } else if (left is IntConstant){
706                                                 int res;
707
708                                                 if (ec.ConstantCheckState)
709                                                         res = checked (((IntConstant) left).Value *
710                                                                        ((IntConstant) right).Value);
711                                                 else
712                                                         res = unchecked (((IntConstant) left).Value *
713                                                                          ((IntConstant) right).Value);
714
715                                                 return new IntConstant (res);
716                                         } else {
717                                                 throw new Exception ( "Unexepected input: " + left);
718                                         }
719                                 } catch (OverflowException){
720                                         Error_CompileTimeOverflow (loc);
721                                 }
722                                 break;
723
724                         case Binary.Operator.Division:
725                                 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
726                                 if (left == null || right == null)
727                                         return null;
728
729                                 try {
730                                         if (left is DoubleConstant){
731                                                 double res;
732                                                 
733                                                 if (ec.ConstantCheckState)
734                                                         res = checked (((DoubleConstant) left).Value /
735                                                                        ((DoubleConstant) right).Value);
736                                                 else
737                                                         res = unchecked (((DoubleConstant) left).Value /
738                                                                          ((DoubleConstant) right).Value);
739                                                 
740                                                 return new DoubleConstant (res);
741                                         } else if (left is FloatConstant){
742                                                 float res;
743                                                 
744                                                 if (ec.ConstantCheckState)
745                                                         res = checked (((FloatConstant) left).Value /
746                                                                        ((FloatConstant) right).Value);
747                                                 else
748                                                         res = unchecked (((FloatConstant) left).Value /
749                                                                          ((FloatConstant) right).Value);
750                                                 
751                                                 return new FloatConstant (res);
752                                         } else if (left is ULongConstant){
753                                                 ulong res;
754                                                 
755                                                 if (ec.ConstantCheckState)
756                                                         res = checked (((ULongConstant) left).Value /
757                                                                        ((ULongConstant) right).Value);
758                                                 else
759                                                         res = unchecked (((ULongConstant) left).Value /
760                                                                          ((ULongConstant) right).Value);
761                                                 
762                                                 return new ULongConstant (res);
763                                         } else if (left is LongConstant){
764                                                 long res;
765                                                 
766                                                 if (ec.ConstantCheckState)
767                                                         res = checked (((LongConstant) left).Value /
768                                                                        ((LongConstant) right).Value);
769                                                 else
770                                                         res = unchecked (((LongConstant) left).Value /
771                                                                          ((LongConstant) right).Value);
772                                                 
773                                                 return new LongConstant (res);
774                                         } else if (left is UIntConstant){
775                                                 uint res;
776                                                 
777                                                 if (ec.ConstantCheckState)
778                                                         res = checked (((UIntConstant) left).Value /
779                                                                        ((UIntConstant) right).Value);
780                                                 else
781                                                         res = unchecked (((UIntConstant) left).Value /
782                                                                          ((UIntConstant) right).Value);
783                                                 
784                                                 return new UIntConstant (res);
785                                         } else if (left is IntConstant){
786                                                 int res;
787
788                                                 if (ec.ConstantCheckState)
789                                                         res = checked (((IntConstant) left).Value /
790                                                                        ((IntConstant) right).Value);
791                                                 else
792                                                         res = unchecked (((IntConstant) left).Value /
793                                                                          ((IntConstant) right).Value);
794
795                                                 return new IntConstant (res);
796                                         } else {
797                                                 throw new Exception ( "Unexepected input: " + left);
798                                         }
799                                 } catch (OverflowException){
800                                         Error_CompileTimeOverflow (loc);
801
802                                 } catch (DivideByZeroException) {
803                                         Report.Error (020, loc, "Division by constant zero");
804                                 }
805                                 
806                                 break;
807                                 
808                         case Binary.Operator.Modulus:
809                                 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
810                                 if (left == null || right == null)
811                                         return null;
812
813                                 try {
814                                         if (left is DoubleConstant){
815                                                 double res;
816                                                 
817                                                 if (ec.ConstantCheckState)
818                                                         res = checked (((DoubleConstant) left).Value %
819                                                                        ((DoubleConstant) right).Value);
820                                                 else
821                                                         res = unchecked (((DoubleConstant) left).Value %
822                                                                          ((DoubleConstant) right).Value);
823                                                 
824                                                 return new DoubleConstant (res);
825                                         } else if (left is FloatConstant){
826                                                 float res;
827                                                 
828                                                 if (ec.ConstantCheckState)
829                                                         res = checked (((FloatConstant) left).Value %
830                                                                        ((FloatConstant) right).Value);
831                                                 else
832                                                         res = unchecked (((FloatConstant) left).Value %
833                                                                          ((FloatConstant) right).Value);
834                                                 
835                                                 return new FloatConstant (res);
836                                         } else if (left is ULongConstant){
837                                                 ulong res;
838                                                 
839                                                 if (ec.ConstantCheckState)
840                                                         res = checked (((ULongConstant) left).Value %
841                                                                        ((ULongConstant) right).Value);
842                                                 else
843                                                         res = unchecked (((ULongConstant) left).Value %
844                                                                          ((ULongConstant) right).Value);
845                                                 
846                                                 return new ULongConstant (res);
847                                         } else if (left is LongConstant){
848                                                 long res;
849                                                 
850                                                 if (ec.ConstantCheckState)
851                                                         res = checked (((LongConstant) left).Value %
852                                                                        ((LongConstant) right).Value);
853                                                 else
854                                                         res = unchecked (((LongConstant) left).Value %
855                                                                          ((LongConstant) right).Value);
856                                                 
857                                                 return new LongConstant (res);
858                                         } else if (left is UIntConstant){
859                                                 uint res;
860                                                 
861                                                 if (ec.ConstantCheckState)
862                                                         res = checked (((UIntConstant) left).Value %
863                                                                        ((UIntConstant) right).Value);
864                                                 else
865                                                         res = unchecked (((UIntConstant) left).Value %
866                                                                          ((UIntConstant) right).Value);
867                                                 
868                                                 return new UIntConstant (res);
869                                         } else if (left is IntConstant){
870                                                 int res;
871
872                                                 if (ec.ConstantCheckState)
873                                                         res = checked (((IntConstant) left).Value %
874                                                                        ((IntConstant) right).Value);
875                                                 else
876                                                         res = unchecked (((IntConstant) left).Value %
877                                                                          ((IntConstant) right).Value);
878
879                                                 return new IntConstant (res);
880                                         } else {
881                                                 throw new Exception ( "Unexepected input: " + left);
882                                         }
883                                 } catch (DivideByZeroException){
884                                         Report.Error (020, loc, "Division by constant zero");
885                                 } catch (OverflowException){
886                                         Error_CompileTimeOverflow (loc);
887                                 }
888                                 break;
889
890                                 //
891                                 // There is no overflow checking on left shift
892                                 //
893                         case Binary.Operator.LeftShift:
894                                 IntConstant ic = right.ToInt (loc);
895                                 if (ic == null){
896                                         Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
897                                         return null;
898                                 }
899                                 int lshift_val = ic.Value;
900
901                                 IntConstant lic;
902                                 if ((lic = left.ConvertToInt ()) != null)
903                                         return new IntConstant (lic.Value << lshift_val);
904
905                                 UIntConstant luic;
906                                 if ((luic = left.ConvertToUInt ()) != null)
907                                         return new UIntConstant (luic.Value << lshift_val);
908
909                                 LongConstant llc;
910                                 if ((llc = left.ConvertToLong ()) != null)
911                                         return new LongConstant (llc.Value << lshift_val);
912
913                                 ULongConstant lulc;
914                                 if ((lulc = left.ConvertToULong ()) != null)
915                                         return new ULongConstant (lulc.Value << lshift_val);
916
917                                 Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
918                                 break;
919
920                                 //
921                                 // There is no overflow checking on right shift
922                                 //
923                         case Binary.Operator.RightShift:
924                                 IntConstant sic = right.ToInt (loc);
925                                 if (sic == null){
926                                         Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
927                                         return null;
928                                 }
929                                 int rshift_val = sic.Value;
930
931                                 IntConstant ric;
932                                 if ((ric = left.ConvertToInt ()) != null)
933                                         return new IntConstant (ric.Value >> rshift_val);
934
935                                 UIntConstant ruic;
936                                 if ((ruic = left.ConvertToUInt ()) != null)
937                                         return new UIntConstant (ruic.Value >> rshift_val);
938
939                                 LongConstant rlc;
940                                 if ((rlc = left.ConvertToLong ()) != null)
941                                         return new LongConstant (rlc.Value >> rshift_val);
942
943                                 ULongConstant rulc;
944                                 if ((rulc = left.ConvertToULong ()) != null)
945                                         return new ULongConstant (rulc.Value >> rshift_val);
946
947                                 Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
948                                 break;
949
950                         case Binary.Operator.LogicalAnd:
951                                 if (left is BoolConstant && right is BoolConstant){
952                                         return new BoolConstant (
953                                                 ((BoolConstant) left).Value &&
954                                                 ((BoolConstant) right).Value);
955                                 }
956                                 break;
957
958                         case Binary.Operator.LogicalOr:
959                                 if (left is BoolConstant && right is BoolConstant){
960                                         return new BoolConstant (
961                                                 ((BoolConstant) left).Value ||
962                                                 ((BoolConstant) right).Value);
963                                 }
964                                 break;
965                                 
966                         case Binary.Operator.Equality:
967                                 if (left is BoolConstant && right is BoolConstant){
968                                         return new BoolConstant (
969                                                 ((BoolConstant) left).Value ==
970                                                 ((BoolConstant) right).Value);
971                                 
972                                 }
973                                 if (left is NullLiteral){
974                                         if (right is NullLiteral)
975                                                 return new BoolConstant (true);
976                                         else if (right is StringConstant)
977                                                 return new BoolConstant (
978                                                         ((StringConstant) right).Value == null);
979                                 } else if (right is NullLiteral){
980                                         if (left is NullLiteral)
981                                                 return new BoolConstant (true);
982                                         else if (left is StringConstant)
983                                                 return new BoolConstant (
984                                                         ((StringConstant) left).Value == null);
985                                 }
986                                 if (left is StringConstant && right is StringConstant){
987                                         return new BoolConstant (
988                                                 ((StringConstant) left).Value ==
989                                                 ((StringConstant) right).Value);
990                                         
991                                 }
992
993                                 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
994                                 if (left == null || right == null)
995                                         return null;
996
997                                 bool_res = false;
998                                 if (left is DoubleConstant)
999                                         bool_res = ((DoubleConstant) left).Value ==
1000                                                 ((DoubleConstant) right).Value;
1001                                 else if (left is FloatConstant)
1002                                         bool_res = ((FloatConstant) left).Value ==
1003                                                 ((FloatConstant) right).Value;
1004                                 else if (left is ULongConstant)
1005                                         bool_res = ((ULongConstant) left).Value ==
1006                                                 ((ULongConstant) right).Value;
1007                                 else if (left is LongConstant)
1008                                         bool_res = ((LongConstant) left).Value ==
1009                                                 ((LongConstant) right).Value;
1010                                 else if (left is UIntConstant)
1011                                         bool_res = ((UIntConstant) left).Value ==
1012                                                 ((UIntConstant) right).Value;
1013                                 else if (left is IntConstant)
1014                                         bool_res = ((IntConstant) left).Value ==
1015                                                 ((IntConstant) right).Value;
1016                                 else
1017                                         return null;
1018
1019                                 return new BoolConstant (bool_res);
1020
1021                         case Binary.Operator.Inequality:
1022                                 if (left is BoolConstant && right is BoolConstant){
1023                                         return new BoolConstant (
1024                                                 ((BoolConstant) left).Value !=
1025                                                 ((BoolConstant) right).Value);
1026                                 }
1027                                 if (left is NullLiteral){
1028                                         if (right is NullLiteral)
1029                                                 return new BoolConstant (false);
1030                                         else if (right is StringConstant)
1031                                                 return new BoolConstant (
1032                                                         ((StringConstant) right).Value != null);
1033                                 } else if (right is NullLiteral){
1034                                         if (left is NullLiteral)
1035                                                 return new BoolConstant (false);
1036                                         else if (left is StringConstant)
1037                                                 return new BoolConstant (
1038                                                         ((StringConstant) left).Value != null);
1039                                 }
1040                                 if (left is StringConstant && right is StringConstant){
1041                                         return new BoolConstant (
1042                                                 ((StringConstant) left).Value !=
1043                                                 ((StringConstant) right).Value);
1044                                         
1045                                 }
1046                                 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1047                                 if (left == null || right == null)
1048                                         return null;
1049
1050                                 bool_res = false;
1051                                 if (left is DoubleConstant)
1052                                         bool_res = ((DoubleConstant) left).Value !=
1053                                                 ((DoubleConstant) right).Value;
1054                                 else if (left is FloatConstant)
1055                                         bool_res = ((FloatConstant) left).Value !=
1056                                                 ((FloatConstant) right).Value;
1057                                 else if (left is ULongConstant)
1058                                         bool_res = ((ULongConstant) left).Value !=
1059                                                 ((ULongConstant) right).Value;
1060                                 else if (left is LongConstant)
1061                                         bool_res = ((LongConstant) left).Value !=
1062                                                 ((LongConstant) right).Value;
1063                                 else if (left is UIntConstant)
1064                                         bool_res = ((UIntConstant) left).Value !=
1065                                                 ((UIntConstant) right).Value;
1066                                 else if (left is IntConstant)
1067                                         bool_res = ((IntConstant) left).Value !=
1068                                                 ((IntConstant) right).Value;
1069                                 else
1070                                         return null;
1071
1072                                 return new BoolConstant (bool_res);
1073
1074                         case Binary.Operator.LessThan:
1075                                 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1076                                 if (left == null || right == null)
1077                                         return null;
1078
1079                                 bool_res = false;
1080                                 if (left is DoubleConstant)
1081                                         bool_res = ((DoubleConstant) left).Value <
1082                                                 ((DoubleConstant) right).Value;
1083                                 else if (left is FloatConstant)
1084                                         bool_res = ((FloatConstant) left).Value <
1085                                                 ((FloatConstant) right).Value;
1086                                 else if (left is ULongConstant)
1087                                         bool_res = ((ULongConstant) left).Value <
1088                                                 ((ULongConstant) right).Value;
1089                                 else if (left is LongConstant)
1090                                         bool_res = ((LongConstant) left).Value <
1091                                                 ((LongConstant) right).Value;
1092                                 else if (left is UIntConstant)
1093                                         bool_res = ((UIntConstant) left).Value <
1094                                                 ((UIntConstant) right).Value;
1095                                 else if (left is IntConstant)
1096                                         bool_res = ((IntConstant) left).Value <
1097                                                 ((IntConstant) right).Value;
1098                                 else
1099                                         return null;
1100
1101                                 return new BoolConstant (bool_res);
1102                                 
1103                         case Binary.Operator.GreaterThan:
1104                                 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1105                                 if (left == null || right == null)
1106                                         return null;
1107
1108                                 bool_res = false;
1109                                 if (left is DoubleConstant)
1110                                         bool_res = ((DoubleConstant) left).Value >
1111                                                 ((DoubleConstant) right).Value;
1112                                 else if (left is FloatConstant)
1113                                         bool_res = ((FloatConstant) left).Value >
1114                                                 ((FloatConstant) right).Value;
1115                                 else if (left is ULongConstant)
1116                                         bool_res = ((ULongConstant) left).Value >
1117                                                 ((ULongConstant) right).Value;
1118                                 else if (left is LongConstant)
1119                                         bool_res = ((LongConstant) left).Value >
1120                                                 ((LongConstant) right).Value;
1121                                 else if (left is UIntConstant)
1122                                         bool_res = ((UIntConstant) left).Value >
1123                                                 ((UIntConstant) right).Value;
1124                                 else if (left is IntConstant)
1125                                         bool_res = ((IntConstant) left).Value >
1126                                                 ((IntConstant) right).Value;
1127                                 else
1128                                         return null;
1129
1130                                 return new BoolConstant (bool_res);
1131
1132                         case Binary.Operator.GreaterThanOrEqual:
1133                                 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1134                                 if (left == null || right == null)
1135                                         return null;
1136
1137                                 bool_res = false;
1138                                 if (left is DoubleConstant)
1139                                         bool_res = ((DoubleConstant) left).Value >=
1140                                                 ((DoubleConstant) right).Value;
1141                                 else if (left is FloatConstant)
1142                                         bool_res = ((FloatConstant) left).Value >=
1143                                                 ((FloatConstant) right).Value;
1144                                 else if (left is ULongConstant)
1145                                         bool_res = ((ULongConstant) left).Value >=
1146                                                 ((ULongConstant) right).Value;
1147                                 else if (left is LongConstant)
1148                                         bool_res = ((LongConstant) left).Value >=
1149                                                 ((LongConstant) right).Value;
1150                                 else if (left is UIntConstant)
1151                                         bool_res = ((UIntConstant) left).Value >=
1152                                                 ((UIntConstant) right).Value;
1153                                 else if (left is IntConstant)
1154                                         bool_res = ((IntConstant) left).Value >=
1155                                                 ((IntConstant) right).Value;
1156                                 else
1157                                         return null;
1158
1159                                 return new BoolConstant (bool_res);
1160
1161                         case Binary.Operator.LessThanOrEqual:
1162                                 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1163                                 if (left == null || right == null)
1164                                         return null;
1165
1166                                 bool_res = false;
1167                                 if (left is DoubleConstant)
1168                                         bool_res = ((DoubleConstant) left).Value <=
1169                                                 ((DoubleConstant) right).Value;
1170                                 else if (left is FloatConstant)
1171                                         bool_res = ((FloatConstant) left).Value <=
1172                                                 ((FloatConstant) right).Value;
1173                                 else if (left is ULongConstant)
1174                                         bool_res = ((ULongConstant) left).Value <=
1175                                                 ((ULongConstant) right).Value;
1176                                 else if (left is LongConstant)
1177                                         bool_res = ((LongConstant) left).Value <=
1178                                                 ((LongConstant) right).Value;
1179                                 else if (left is UIntConstant)
1180                                         bool_res = ((UIntConstant) left).Value <=
1181                                                 ((UIntConstant) right).Value;
1182                                 else if (left is IntConstant)
1183                                         bool_res = ((IntConstant) left).Value <=
1184                                                 ((IntConstant) right).Value;
1185                                 else
1186                                         return null;
1187
1188                                 return new BoolConstant (bool_res);
1189                         }
1190                                         
1191                         return null;
1192                 }
1193         }
1194 }