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