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