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