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