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