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