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