Add Constant Folder
[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 (true, loc);
40
41                                 if (!(right is DoubleConstant))
42                                         right = right.ToDouble (true, 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 (true, loc);
50
51                                 if (!(right is FloatConstant))
52                                         right = right.ToFloat (true, 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 (true, loc);
67                                 } else {
68                                         other = left;
69                                         match = right;
70                                         left = left.ToULong (true, 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 (true, loc);
88                                 else if (!(right is LongConstant))
89                                         right = right.ToLong (true, 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 (true, loc);
99                                 else if (!(right is UIntConstant))
100                                         right = right.ToUInt (true, loc);
101                                 return;
102                         } else {
103                                 //
104                                 // Force conversions to int32
105                                 //
106                                 if (!(left is IntConstant))
107                                         left = left.ToInt (true, loc);
108                                 if (!(right is IntConstant))
109                                         right = right.ToInt (true, 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                                 if (left is StringConstant && right is StringConstant)
276                                         return new StringConstant (
277                                                 ((StringConstant) left).Value +
278                                                 ((StringConstant) right).Value);
279
280                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);
281                                 if (left == null || right == null)
282                                         return null;
283
284                                 try {
285                                         if (left is DoubleConstant){
286                                                 double res;
287                                                 
288                                                 if (ec.ConstantCheckState)
289                                                         res = checked (((DoubleConstant) left).Value +
290                                                                        ((DoubleConstant) right).Value);
291                                                 else
292                                                         res = unchecked (((DoubleConstant) left).Value +
293                                                                          ((DoubleConstant) right).Value);
294                                                 
295                                                 return new DoubleConstant (res);
296                                         } else if (left is FloatConstant){
297                                                 float res;
298                                                 
299                                                 if (ec.ConstantCheckState)
300                                                         res = checked (((FloatConstant) left).Value +
301                                                                        ((FloatConstant) right).Value);
302                                                 else
303                                                         res = unchecked (((FloatConstant) left).Value +
304                                                                          ((FloatConstant) right).Value);
305                                                 
306                                                 return new FloatConstant (res);
307                                         } else if (left is ULongConstant){
308                                                 ulong res;
309                                                 
310                                                 if (ec.ConstantCheckState)
311                                                         res = checked (((ULongConstant) left).Value +
312                                                                        ((ULongConstant) right).Value);
313                                                 else
314                                                         res = unchecked (((ULongConstant) left).Value +
315                                                                          ((ULongConstant) right).Value);
316                                                 
317                                                 return new ULongConstant (res);
318                                         } else if (left is LongConstant){
319                                                 long res;
320                                                 
321                                                 if (ec.ConstantCheckState)
322                                                         res = checked (((LongConstant) left).Value +
323                                                                        ((LongConstant) right).Value);
324                                                 else
325                                                         res = unchecked (((LongConstant) left).Value +
326                                                                          ((LongConstant) right).Value);
327                                                 
328                                                 return new LongConstant (res);
329                                         } else if (left is UIntConstant){
330                                                 uint res;
331                                                 
332                                                 if (ec.ConstantCheckState)
333                                                         res = checked (((UIntConstant) left).Value +
334                                                                        ((UIntConstant) right).Value);
335                                                 else
336                                                         res = unchecked (((UIntConstant) left).Value +
337                                                                          ((UIntConstant) right).Value);
338                                                 
339                                                 return new UIntConstant (res);
340                                         } else if (left is IntConstant){
341                                                 int res;
342
343                                                 if (ec.ConstantCheckState)
344                                                         res = checked (((IntConstant) left).Value +
345                                                                        ((IntConstant) right).Value);
346                                                 else
347                                                         res = unchecked (((IntConstant) left).Value +
348                                                                          ((IntConstant) right).Value);
349
350                                                 return new IntConstant (res);
351                                         } else {
352                                                 throw new Exception ( "Unexepected input: " + left);
353                                         }
354                                 } catch (OverflowException){
355                                         Error_CompileTimeOverflow (loc);
356                                 }
357                                 break;
358
359                         case Binary.Operator.Subtraction:
360                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);
361                                 if (left == null || right == null)
362                                         return null;
363
364                                 try {
365                                         if (left is DoubleConstant){
366                                                 double res;
367                                                 
368                                                 if (ec.ConstantCheckState)
369                                                         res = checked (((DoubleConstant) left).Value -
370                                                                        ((DoubleConstant) right).Value);
371                                                 else
372                                                         res = unchecked (((DoubleConstant) left).Value -
373                                                                          ((DoubleConstant) right).Value);
374                                                 
375                                                 return new DoubleConstant (res);
376                                         } else if (left is FloatConstant){
377                                                 float res;
378                                                 
379                                                 if (ec.ConstantCheckState)
380                                                         res = checked (((FloatConstant) left).Value -
381                                                                        ((FloatConstant) right).Value);
382                                                 else
383                                                         res = unchecked (((FloatConstant) left).Value -
384                                                                          ((FloatConstant) right).Value);
385                                                 
386                                                 return new FloatConstant (res);
387                                         } else if (left is ULongConstant){
388                                                 ulong res;
389                                                 
390                                                 if (ec.ConstantCheckState)
391                                                         res = checked (((ULongConstant) left).Value -
392                                                                        ((ULongConstant) right).Value);
393                                                 else
394                                                         res = unchecked (((ULongConstant) left).Value -
395                                                                          ((ULongConstant) right).Value);
396                                                 
397                                                 return new ULongConstant (res);
398                                         } else if (left is LongConstant){
399                                                 long res;
400                                                 
401                                                 if (ec.ConstantCheckState)
402                                                         res = checked (((LongConstant) left).Value -
403                                                                        ((LongConstant) right).Value);
404                                                 else
405                                                         res = unchecked (((LongConstant) left).Value -
406                                                                          ((LongConstant) right).Value);
407                                                 
408                                                 return new LongConstant (res);
409                                         } else if (left is UIntConstant){
410                                                 uint res;
411                                                 
412                                                 if (ec.ConstantCheckState)
413                                                         res = checked (((UIntConstant) left).Value -
414                                                                        ((UIntConstant) right).Value);
415                                                 else
416                                                         res = unchecked (((UIntConstant) left).Value -
417                                                                          ((UIntConstant) right).Value);
418                                                 
419                                                 return new UIntConstant (res);
420                                         } else if (left is IntConstant){
421                                                 int res;
422
423                                                 if (ec.ConstantCheckState)
424                                                         res = checked (((IntConstant) left).Value -
425                                                                        ((IntConstant) right).Value);
426                                                 else
427                                                         res = unchecked (((IntConstant) left).Value -
428                                                                          ((IntConstant) right).Value);
429
430                                                 return new IntConstant (res);
431                                         } else {
432                                                 throw new Exception ( "Unexepected input: " + left);
433                                         }
434                                 } catch (OverflowException){
435                                         Error_CompileTimeOverflow (loc);
436                                 }
437                                 break;
438                                 
439                         case Binary.Operator.Multiply:
440                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);
441                                 if (left == null || right == null)
442                                         return null;
443
444                                 try {
445                                         if (left is DoubleConstant){
446                                                 double res;
447                                                 
448                                                 if (ec.ConstantCheckState)
449                                                         res = checked (((DoubleConstant) left).Value *
450                                                                        ((DoubleConstant) right).Value);
451                                                 else
452                                                         res = unchecked (((DoubleConstant) left).Value *
453                                                                          ((DoubleConstant) right).Value);
454                                                 
455                                                 return new DoubleConstant (res);
456                                         } else if (left is FloatConstant){
457                                                 float res;
458                                                 
459                                                 if (ec.ConstantCheckState)
460                                                         res = checked (((FloatConstant) left).Value *
461                                                                        ((FloatConstant) right).Value);
462                                                 else
463                                                         res = unchecked (((FloatConstant) left).Value *
464                                                                          ((FloatConstant) right).Value);
465                                                 
466                                                 return new FloatConstant (res);
467                                         } else if (left is ULongConstant){
468                                                 ulong res;
469                                                 
470                                                 if (ec.ConstantCheckState)
471                                                         res = checked (((ULongConstant) left).Value *
472                                                                        ((ULongConstant) right).Value);
473                                                 else
474                                                         res = unchecked (((ULongConstant) left).Value *
475                                                                          ((ULongConstant) right).Value);
476                                                 
477                                                 return new ULongConstant (res);
478                                         } else if (left is LongConstant){
479                                                 long res;
480                                                 
481                                                 if (ec.ConstantCheckState)
482                                                         res = checked (((LongConstant) left).Value *
483                                                                        ((LongConstant) right).Value);
484                                                 else
485                                                         res = unchecked (((LongConstant) left).Value *
486                                                                          ((LongConstant) right).Value);
487                                                 
488                                                 return new LongConstant (res);
489                                         } else if (left is UIntConstant){
490                                                 uint res;
491                                                 
492                                                 if (ec.ConstantCheckState)
493                                                         res = checked (((UIntConstant) left).Value *
494                                                                        ((UIntConstant) right).Value);
495                                                 else
496                                                         res = unchecked (((UIntConstant) left).Value *
497                                                                          ((UIntConstant) right).Value);
498                                                 
499                                                 return new UIntConstant (res);
500                                         } else if (left is IntConstant){
501                                                 int res;
502
503                                                 if (ec.ConstantCheckState)
504                                                         res = checked (((IntConstant) left).Value *
505                                                                        ((IntConstant) right).Value);
506                                                 else
507                                                         res = unchecked (((IntConstant) left).Value *
508                                                                          ((IntConstant) right).Value);
509
510                                                 return new IntConstant (res);
511                                         } else {
512                                                 throw new Exception ( "Unexepected input: " + left);
513                                         }
514                                 } catch (OverflowException){
515                                         Error_CompileTimeOverflow (loc);
516                                 }
517                                 break;
518
519                         case Binary.Operator.Division:
520                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);
521                                 if (left == null || right == null)
522                                         return null;
523
524                                 try {
525                                         if (left is DoubleConstant){
526                                                 double res;
527                                                 
528                                                 if (ec.ConstantCheckState)
529                                                         res = checked (((DoubleConstant) left).Value /
530                                                                        ((DoubleConstant) right).Value);
531                                                 else
532                                                         res = unchecked (((DoubleConstant) left).Value /
533                                                                          ((DoubleConstant) right).Value);
534                                                 
535                                                 return new DoubleConstant (res);
536                                         } else if (left is FloatConstant){
537                                                 float res;
538                                                 
539                                                 if (ec.ConstantCheckState)
540                                                         res = checked (((FloatConstant) left).Value /
541                                                                        ((FloatConstant) right).Value);
542                                                 else
543                                                         res = unchecked (((FloatConstant) left).Value /
544                                                                          ((FloatConstant) right).Value);
545                                                 
546                                                 return new FloatConstant (res);
547                                         } else if (left is ULongConstant){
548                                                 ulong res;
549                                                 
550                                                 if (ec.ConstantCheckState)
551                                                         res = checked (((ULongConstant) left).Value /
552                                                                        ((ULongConstant) right).Value);
553                                                 else
554                                                         res = unchecked (((ULongConstant) left).Value /
555                                                                          ((ULongConstant) right).Value);
556                                                 
557                                                 return new ULongConstant (res);
558                                         } else if (left is LongConstant){
559                                                 long res;
560                                                 
561                                                 if (ec.ConstantCheckState)
562                                                         res = checked (((LongConstant) left).Value /
563                                                                        ((LongConstant) right).Value);
564                                                 else
565                                                         res = unchecked (((LongConstant) left).Value /
566                                                                          ((LongConstant) right).Value);
567                                                 
568                                                 return new LongConstant (res);
569                                         } else if (left is UIntConstant){
570                                                 uint res;
571                                                 
572                                                 if (ec.ConstantCheckState)
573                                                         res = checked (((UIntConstant) left).Value /
574                                                                        ((UIntConstant) right).Value);
575                                                 else
576                                                         res = unchecked (((UIntConstant) left).Value /
577                                                                          ((UIntConstant) right).Value);
578                                                 
579                                                 return new UIntConstant (res);
580                                         } else if (left is IntConstant){
581                                                 int res;
582
583                                                 if (ec.ConstantCheckState)
584                                                         res = checked (((IntConstant) left).Value /
585                                                                        ((IntConstant) right).Value);
586                                                 else
587                                                         res = unchecked (((IntConstant) left).Value /
588                                                                          ((IntConstant) right).Value);
589
590                                                 return new IntConstant (res);
591                                         } else {
592                                                 throw new Exception ( "Unexepected input: " + left);
593                                         }
594                                 } catch (OverflowException){
595                                         Error_CompileTimeOverflow (loc);
596                                 }
597                                 break;
598                                 
599                         case Binary.Operator.Modulus:
600                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);
601                                 if (left == null || right == null)
602                                         return null;
603
604                                 try {
605                                         if (left is DoubleConstant){
606                                                 double res;
607                                                 
608                                                 if (ec.ConstantCheckState)
609                                                         res = checked (((DoubleConstant) left).Value %
610                                                                        ((DoubleConstant) right).Value);
611                                                 else
612                                                         res = unchecked (((DoubleConstant) left).Value %
613                                                                          ((DoubleConstant) right).Value);
614                                                 
615                                                 return new DoubleConstant (res);
616                                         } else if (left is FloatConstant){
617                                                 float res;
618                                                 
619                                                 if (ec.ConstantCheckState)
620                                                         res = checked (((FloatConstant) left).Value %
621                                                                        ((FloatConstant) right).Value);
622                                                 else
623                                                         res = unchecked (((FloatConstant) left).Value %
624                                                                          ((FloatConstant) right).Value);
625                                                 
626                                                 return new FloatConstant (res);
627                                         } else if (left is ULongConstant){
628                                                 ulong res;
629                                                 
630                                                 if (ec.ConstantCheckState)
631                                                         res = checked (((ULongConstant) left).Value %
632                                                                        ((ULongConstant) right).Value);
633                                                 else
634                                                         res = unchecked (((ULongConstant) left).Value %
635                                                                          ((ULongConstant) right).Value);
636                                                 
637                                                 return new ULongConstant (res);
638                                         } else if (left is LongConstant){
639                                                 long res;
640                                                 
641                                                 if (ec.ConstantCheckState)
642                                                         res = checked (((LongConstant) left).Value %
643                                                                        ((LongConstant) right).Value);
644                                                 else
645                                                         res = unchecked (((LongConstant) left).Value %
646                                                                          ((LongConstant) right).Value);
647                                                 
648                                                 return new LongConstant (res);
649                                         } else if (left is UIntConstant){
650                                                 uint res;
651                                                 
652                                                 if (ec.ConstantCheckState)
653                                                         res = checked (((UIntConstant) left).Value %
654                                                                        ((UIntConstant) right).Value);
655                                                 else
656                                                         res = unchecked (((UIntConstant) left).Value %
657                                                                          ((UIntConstant) right).Value);
658                                                 
659                                                 return new UIntConstant (res);
660                                         } else if (left is IntConstant){
661                                                 int res;
662
663                                                 if (ec.ConstantCheckState)
664                                                         res = checked (((IntConstant) left).Value %
665                                                                        ((IntConstant) right).Value);
666                                                 else
667                                                         res = unchecked (((IntConstant) left).Value %
668                                                                          ((IntConstant) right).Value);
669
670                                                 return new IntConstant (res);
671                                         } else {
672                                                 throw new Exception ( "Unexepected input: " + left);
673                                         }
674                                 } catch (OverflowException){
675                                         Error_CompileTimeOverflow (loc);
676                                 }
677                                 break;
678
679                                 //
680                                 // There is no overflow checking on left shift
681                                 //
682                         case Binary.Operator.LeftShift:
683                                 IntConstant ic = right.ToInt (true, loc);
684                                 if (ic == null){
685                                         Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
686                                         return null;
687                                 }
688                                 int lshift_val = ic.Value;
689
690                                 IntConstant lic;
691                                 if ((lic = left.ConvertToInt (true)) != null)
692                                         return new IntConstant (lic.Value << lshift_val);
693
694                                 UIntConstant luic;
695                                 if ((luic = left.ConvertToUInt (true)) != null)
696                                         return new UIntConstant (luic.Value << lshift_val);
697
698                                 LongConstant llc;
699                                 if ((llc = left.ConvertToLong (true)) != null)
700                                         return new LongConstant (llc.Value << lshift_val);
701
702                                 ULongConstant lulc;
703                                 if ((lulc = left.ConvertToULong (true)) != null)
704                                         return new ULongConstant (lulc.Value << lshift_val);
705
706                                 Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
707                                 break;
708
709                                 //
710                                 // There is no overflow checking on right shift
711                                 //
712                         case Binary.Operator.RightShift:
713                                 IntConstant sic = right.ToInt (true, loc);
714                                 if (sic == null){
715                                         Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
716                                         return null;
717                                 }
718                                 int rshift_val = sic.Value;
719
720                                 IntConstant ric;
721                                 if ((ric = left.ConvertToInt (true)) != null)
722                                         return new IntConstant (ric.Value >> rshift_val);
723
724                                 UIntConstant ruic;
725                                 if ((ruic = left.ConvertToUInt (true)) != null)
726                                         return new UIntConstant (ruic.Value >> rshift_val);
727
728                                 LongConstant rlc;
729                                 if ((rlc = left.ConvertToLong (true)) != null)
730                                         return new LongConstant (rlc.Value >> rshift_val);
731
732                                 ULongConstant rulc;
733                                 if ((rulc = left.ConvertToULong (true)) != null)
734                                         return new ULongConstant (rulc.Value >> rshift_val);
735
736                                 Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
737                                 break;
738
739                         case Binary.Operator.LogicalAnd:
740                                 if (left is BoolConstant && right is BoolConstant){
741                                         return new BoolConstant (
742                                                 ((BoolConstant) left).Value &&
743                                                 ((BoolConstant) right).Value);
744                                 }
745                                 break;
746
747                         case Binary.Operator.LogicalOr:
748                                 if (left is BoolConstant && right is BoolConstant){
749                                         return new BoolConstant (
750                                                 ((BoolConstant) left).Value ||
751                                                 ((BoolConstant) right).Value);
752                                 }
753                                 break;
754                                 
755                         case Binary.Operator.Equality:
756                                 if (left is BoolConstant && right is BoolConstant){
757                                         return new BoolConstant (
758                                                 ((BoolConstant) left).Value ==
759                                                 ((BoolConstant) right).Value);
760                                 
761                                 }
762                                 if (left is StringConstant && right is StringConstant){
763                                         return new BoolConstant (
764                                                 ((StringConstant) left).Value ==
765                                                 ((StringConstant) right).Value);
766                                         
767                                 }
768                                 
769                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);
770                                 if (left == null || right == null)
771                                         return null;
772
773                                 bool_res = false;
774                                 if (left is DoubleConstant)
775                                         bool_res = ((DoubleConstant) left).Value ==
776                                                 ((DoubleConstant) right).Value;
777                                 else if (left is FloatConstant)
778                                         bool_res = ((FloatConstant) left).Value ==
779                                                 ((FloatConstant) right).Value;
780                                 else if (left is ULongConstant)
781                                         bool_res = ((ULongConstant) left).Value ==
782                                                 ((ULongConstant) right).Value;
783                                 else if (left is LongConstant)
784                                         bool_res = ((LongConstant) left).Value ==
785                                                 ((LongConstant) right).Value;
786                                 else if (left is UIntConstant)
787                                         bool_res = ((UIntConstant) left).Value ==
788                                                 ((UIntConstant) right).Value;
789                                 else if (left is IntConstant)
790                                         bool_res = ((IntConstant) left).Value ==
791                                                 ((IntConstant) right).Value;
792                                 else
793                                         return null;
794
795                                 return new BoolConstant (bool_res);
796
797                         case Binary.Operator.Inequality:
798                                 if (left is BoolConstant && right is BoolConstant){
799                                         return new BoolConstant (
800                                                 ((BoolConstant) left).Value !=
801                                                 ((BoolConstant) right).Value);
802                                 }
803                                 if (left is StringConstant && right is StringConstant){
804                                         return new BoolConstant (
805                                                 ((StringConstant) left).Value !=
806                                                 ((StringConstant) right).Value);
807                                         
808                                 }
809                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);
810                                 if (left == null || right == null)
811                                         return null;
812
813                                 bool_res = false;
814                                 if (left is DoubleConstant)
815                                         bool_res = ((DoubleConstant) left).Value !=
816                                                 ((DoubleConstant) right).Value;
817                                 else if (left is FloatConstant)
818                                         bool_res = ((FloatConstant) left).Value !=
819                                                 ((FloatConstant) right).Value;
820                                 else if (left is ULongConstant)
821                                         bool_res = ((ULongConstant) left).Value !=
822                                                 ((ULongConstant) right).Value;
823                                 else if (left is LongConstant)
824                                         bool_res = ((LongConstant) left).Value !=
825                                                 ((LongConstant) right).Value;
826                                 else if (left is UIntConstant)
827                                         bool_res = ((UIntConstant) left).Value !=
828                                                 ((UIntConstant) right).Value;
829                                 else if (left is IntConstant)
830                                         bool_res = ((IntConstant) left).Value !=
831                                                 ((IntConstant) right).Value;
832                                 else
833                                         return null;
834
835                                 return new BoolConstant (bool_res);
836
837                         case Binary.Operator.LessThan:
838                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);
839                                 if (left == null || right == null)
840                                         return null;
841
842                                 bool_res = false;
843                                 if (left is DoubleConstant)
844                                         bool_res = ((DoubleConstant) left).Value <
845                                                 ((DoubleConstant) right).Value;
846                                 else if (left is FloatConstant)
847                                         bool_res = ((FloatConstant) left).Value <
848                                                 ((FloatConstant) right).Value;
849                                 else if (left is ULongConstant)
850                                         bool_res = ((ULongConstant) left).Value <
851                                                 ((ULongConstant) right).Value;
852                                 else if (left is LongConstant)
853                                         bool_res = ((LongConstant) left).Value <
854                                                 ((LongConstant) right).Value;
855                                 else if (left is UIntConstant)
856                                         bool_res = ((UIntConstant) left).Value <
857                                                 ((UIntConstant) right).Value;
858                                 else if (left is IntConstant)
859                                         bool_res = ((IntConstant) left).Value <
860                                                 ((IntConstant) right).Value;
861                                 else
862                                         return null;
863
864                                 return new BoolConstant (bool_res);
865                                 
866                         case Binary.Operator.GreaterThan:
867                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);
868                                 if (left == null || right == null)
869                                         return null;
870
871                                 bool_res = false;
872                                 if (left is DoubleConstant)
873                                         bool_res = ((DoubleConstant) left).Value >
874                                                 ((DoubleConstant) right).Value;
875                                 else if (left is FloatConstant)
876                                         bool_res = ((FloatConstant) left).Value >
877                                                 ((FloatConstant) right).Value;
878                                 else if (left is ULongConstant)
879                                         bool_res = ((ULongConstant) left).Value >
880                                                 ((ULongConstant) right).Value;
881                                 else if (left is LongConstant)
882                                         bool_res = ((LongConstant) left).Value >
883                                                 ((LongConstant) right).Value;
884                                 else if (left is UIntConstant)
885                                         bool_res = ((UIntConstant) left).Value >
886                                                 ((UIntConstant) right).Value;
887                                 else if (left is IntConstant)
888                                         bool_res = ((IntConstant) left).Value >
889                                                 ((IntConstant) right).Value;
890                                 else
891                                         return null;
892
893                                 return new BoolConstant (bool_res);
894
895                         case Binary.Operator.GreaterThanOrEqual:
896                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);
897                                 if (left == null || right == null)
898                                         return null;
899
900                                 bool_res = false;
901                                 if (left is DoubleConstant)
902                                         bool_res = ((DoubleConstant) left).Value >=
903                                                 ((DoubleConstant) right).Value;
904                                 else if (left is FloatConstant)
905                                         bool_res = ((FloatConstant) left).Value >=
906                                                 ((FloatConstant) right).Value;
907                                 else if (left is ULongConstant)
908                                         bool_res = ((ULongConstant) left).Value >=
909                                                 ((ULongConstant) right).Value;
910                                 else if (left is LongConstant)
911                                         bool_res = ((LongConstant) left).Value >=
912                                                 ((LongConstant) right).Value;
913                                 else if (left is UIntConstant)
914                                         bool_res = ((UIntConstant) left).Value >=
915                                                 ((UIntConstant) right).Value;
916                                 else if (left is IntConstant)
917                                         bool_res = ((IntConstant) left).Value >=
918                                                 ((IntConstant) right).Value;
919                                 else
920                                         return null;
921
922                                 return new BoolConstant (bool_res);
923
924                         case Binary.Operator.LessThanOrEqual:
925                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);
926                                 if (left == null || right == null)
927                                         return null;
928
929                                 bool_res = false;
930                                 if (left is DoubleConstant)
931                                         bool_res = ((DoubleConstant) left).Value <=
932                                                 ((DoubleConstant) right).Value;
933                                 else if (left is FloatConstant)
934                                         bool_res = ((FloatConstant) left).Value <=
935                                                 ((FloatConstant) right).Value;
936                                 else if (left is ULongConstant)
937                                         bool_res = ((ULongConstant) left).Value <=
938                                                 ((ULongConstant) right).Value;
939                                 else if (left is LongConstant)
940                                         bool_res = ((LongConstant) left).Value <=
941                                                 ((LongConstant) right).Value;
942                                 else if (left is UIntConstant)
943                                         bool_res = ((UIntConstant) left).Value <=
944                                                 ((UIntConstant) right).Value;
945                                 else if (left is IntConstant)
946                                         bool_res = ((IntConstant) left).Value <=
947                                                 ((IntConstant) right).Value;
948                                 else
949                                         return null;
950
951                                 return new BoolConstant (bool_res);
952                         }
953                                         
954                         return null;
955                 }
956         }
957 }