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