2010-06-21 Atsushi Enomoto <atsushi@ximian.com>
[mcs.git] / mcs / cfold.cs
blobb8b82ffe573f99a60cec30aaf0444ebb22f00810
1 //
2 // cfold.cs: Constant Folding
3 //
4 // Author:
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
7 //
8 // Copyright 2002, 2003 Ximian, Inc.
9 // Copyright 2003-2008, Novell, Inc.
10 //
11 using System;
13 namespace Mono.CSharp {
15 public class ConstantFold {
17 static TypeSpec[] binary_promotions;
19 public static TypeSpec[] BinaryPromotionsTypes {
20 get {
21 if (binary_promotions == null) {
22 binary_promotions = new TypeSpec[] {
23 TypeManager.decimal_type, TypeManager.double_type, TypeManager.float_type,
24 TypeManager.uint64_type, TypeManager.int64_type, TypeManager.uint32_type };
27 return binary_promotions;
31 public static void Reset ()
33 binary_promotions = null;
37 // Performs the numeric promotions on the left and right expresions
38 // and deposits the results on `lc' and `rc'.
40 // On success, the types of `lc' and `rc' on output will always match,
41 // and the pair will be one of:
43 // TODO: BinaryFold should be called as an optimization step only,
44 // error checking here is weak
45 //
46 static bool DoBinaryNumericPromotions (ResolveContext rc, ref Constant left, ref Constant right)
48 TypeSpec ltype = left.Type;
49 TypeSpec rtype = right.Type;
51 foreach (TypeSpec t in BinaryPromotionsTypes) {
52 if (t == ltype)
53 return t == rtype || ConvertPromotion (rc, ref right, ref left, t);
55 if (t == rtype)
56 return t == ltype || ConvertPromotion (rc, ref left, ref right, t);
59 left = left.ConvertImplicitly (rc, TypeManager.int32_type);
60 right = right.ConvertImplicitly (rc, TypeManager.int32_type);
61 return left != null && right != null;
64 static bool ConvertPromotion (ResolveContext rc, ref Constant prim, ref Constant second, TypeSpec type)
66 Constant c = prim.ConvertImplicitly (rc, type);
67 if (c != null) {
68 prim = c;
69 return true;
72 if (type == TypeManager.uint32_type) {
73 type = TypeManager.int64_type;
74 prim = prim.ConvertImplicitly (rc, type);
75 second = second.ConvertImplicitly (rc, type);
76 return prim != null && second != null;
79 return false;
82 internal static void Error_CompileTimeOverflow (ResolveContext rc, Location loc)
84 rc.Report.Error (220, loc, "The operation overflows at compile time in checked mode");
87 /// <summary>
88 /// Constant expression folder for binary operations.
89 ///
90 /// Returns null if the expression can not be folded.
91 /// </summary>
92 static public Constant BinaryFold (ResolveContext ec, Binary.Operator oper,
93 Constant left, Constant right, Location loc)
95 Constant result = null;
97 if (left is EmptyConstantCast)
98 return BinaryFold (ec, oper, ((EmptyConstantCast)left).child, right, loc);
100 if (left is SideEffectConstant) {
101 result = BinaryFold (ec, oper, ((SideEffectConstant) left).value, right, loc);
102 if (result == null)
103 return null;
104 return new SideEffectConstant (result, left, loc);
107 if (right is EmptyConstantCast)
108 return BinaryFold (ec, oper, left, ((EmptyConstantCast)right).child, loc);
110 if (right is SideEffectConstant) {
111 result = BinaryFold (ec, oper, left, ((SideEffectConstant) right).value, loc);
112 if (result == null)
113 return null;
114 return new SideEffectConstant (result, right, loc);
117 TypeSpec lt = left.Type;
118 TypeSpec rt = right.Type;
119 bool bool_res;
121 if (lt == TypeManager.bool_type && lt == rt) {
122 bool lv = (bool) left.GetValue ();
123 bool rv = (bool) right.GetValue ();
124 switch (oper) {
125 case Binary.Operator.BitwiseAnd:
126 case Binary.Operator.LogicalAnd:
127 return new BoolConstant (lv && rv, left.Location);
128 case Binary.Operator.BitwiseOr:
129 case Binary.Operator.LogicalOr:
130 return new BoolConstant (lv || rv, left.Location);
131 case Binary.Operator.ExclusiveOr:
132 return new BoolConstant (lv ^ rv, left.Location);
133 case Binary.Operator.Equality:
134 return new BoolConstant (lv == rv, left.Location);
135 case Binary.Operator.Inequality:
136 return new BoolConstant (lv != rv, left.Location);
138 return null;
142 // During an enum evaluation, none of the rules are valid
143 // Not sure whether it is bug in csc or in documentation
145 if (ec.HasSet (ResolveContext.Options.EnumScope)){
146 if (left is EnumConstant)
147 left = ((EnumConstant) left).Child;
149 if (right is EnumConstant)
150 right = ((EnumConstant) right).Child;
151 } else if (left is EnumConstant && rt == lt) {
152 switch (oper){
154 /// E operator |(E x, E y);
155 /// E operator &(E x, E y);
156 /// E operator ^(E x, E y);
157 ///
158 case Binary.Operator.BitwiseOr:
159 case Binary.Operator.BitwiseAnd:
160 case Binary.Operator.ExclusiveOr:
161 result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
162 if (result != null)
163 result = result.Resolve (ec).TryReduce (ec, lt, loc);
164 return result;
167 /// U operator -(E x, E y);
168 ///
169 case Binary.Operator.Subtraction:
170 result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
171 if (result != null)
172 result = result.Resolve (ec).TryReduce (ec, ((EnumConstant)left).Child.Type, loc);
173 return result;
176 /// bool operator ==(E x, E y);
177 /// bool operator !=(E x, E y);
178 /// bool operator <(E x, E y);
179 /// bool operator >(E x, E y);
180 /// bool operator <=(E x, E y);
181 /// bool operator >=(E x, E y);
182 ///
183 case Binary.Operator.Equality:
184 case Binary.Operator.Inequality:
185 case Binary.Operator.LessThan:
186 case Binary.Operator.GreaterThan:
187 case Binary.Operator.LessThanOrEqual:
188 case Binary.Operator.GreaterThanOrEqual:
189 return BinaryFold(ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
191 return null;
194 switch (oper){
195 case Binary.Operator.BitwiseOr:
196 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
197 return null;
199 if (left is IntConstant){
200 int res = ((IntConstant) left).Value | ((IntConstant) right).Value;
202 return new IntConstant (res, left.Location);
204 if (left is UIntConstant){
205 uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value;
207 return new UIntConstant (res, left.Location);
209 if (left is LongConstant){
210 long res = ((LongConstant)left).Value | ((LongConstant)right).Value;
212 return new LongConstant (res, left.Location);
214 if (left is ULongConstant){
215 ulong res = ((ULongConstant)left).Value |
216 ((ULongConstant)right).Value;
218 return new ULongConstant (res, left.Location);
220 break;
222 case Binary.Operator.BitwiseAnd:
223 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
224 return null;
227 /// int operator &(int x, int y);
228 /// uint operator &(uint x, uint y);
229 /// long operator &(long x, long y);
230 /// ulong operator &(ulong x, ulong y);
232 if (left is IntConstant){
233 int res = ((IntConstant) left).Value & ((IntConstant) right).Value;
234 return new IntConstant (res, left.Location);
236 if (left is UIntConstant){
237 uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value;
238 return new UIntConstant (res, left.Location);
240 if (left is LongConstant){
241 long res = ((LongConstant)left).Value & ((LongConstant)right).Value;
242 return new LongConstant (res, left.Location);
244 if (left is ULongConstant){
245 ulong res = ((ULongConstant)left).Value &
246 ((ULongConstant)right).Value;
248 return new ULongConstant (res, left.Location);
250 break;
252 case Binary.Operator.ExclusiveOr:
253 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
254 return null;
256 if (left is IntConstant){
257 int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value;
258 return new IntConstant (res, left.Location);
260 if (left is UIntConstant){
261 uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value;
263 return new UIntConstant (res, left.Location);
265 if (left is LongConstant){
266 long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value;
268 return new LongConstant (res, left.Location);
270 if (left is ULongConstant){
271 ulong res = ((ULongConstant)left).Value ^
272 ((ULongConstant)right).Value;
274 return new ULongConstant (res, left.Location);
276 break;
278 case Binary.Operator.Addition:
279 if (lt == TypeManager.null_type)
280 return right;
282 if (rt == TypeManager.null_type)
283 return left;
286 // If both sides are strings, then concatenate, if
287 // one is a string, and the other is not, then defer
288 // to runtime concatenation
290 if (lt == TypeManager.string_type || rt == TypeManager.string_type){
291 if (lt == rt)
292 return new StringConstant ((string)left.GetValue () + (string)right.GetValue (),
293 left.Location);
295 return null;
299 // handle "E operator + (E x, U y)"
300 // handle "E operator + (Y y, E x)"
302 EnumConstant lc = left as EnumConstant;
303 EnumConstant rc = right as EnumConstant;
304 if (lc != null || rc != null){
305 if (lc == null) {
306 lc = rc;
307 lt = lc.Type;
308 right = left;
311 // U has to be implicitly convetible to E.base
312 right = right.ConvertImplicitly (ec, lc.Child.Type);
313 if (right == null)
314 return null;
316 result = BinaryFold (ec, oper, lc.Child, right, loc);
317 if (result == null)
318 return null;
320 result = result.Resolve (ec).TryReduce (ec, lt, loc);
321 if (result == null)
322 return null;
324 return new EnumConstant (result, lt);
327 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
328 return null;
330 try {
331 if (left is DoubleConstant){
332 double res;
334 if (ec.ConstantCheckState)
335 res = checked (((DoubleConstant) left).Value +
336 ((DoubleConstant) right).Value);
337 else
338 res = unchecked (((DoubleConstant) left).Value +
339 ((DoubleConstant) right).Value);
341 return new DoubleConstant (res, left.Location);
343 if (left is FloatConstant){
344 float res;
346 if (ec.ConstantCheckState)
347 res = checked (((FloatConstant) left).Value +
348 ((FloatConstant) right).Value);
349 else
350 res = unchecked (((FloatConstant) left).Value +
351 ((FloatConstant) right).Value);
353 result = new FloatConstant (res, left.Location);
354 } else if (left is ULongConstant){
355 ulong res;
357 if (ec.ConstantCheckState)
358 res = checked (((ULongConstant) left).Value +
359 ((ULongConstant) right).Value);
360 else
361 res = unchecked (((ULongConstant) left).Value +
362 ((ULongConstant) right).Value);
364 result = new ULongConstant (res, left.Location);
365 } else if (left is LongConstant){
366 long res;
368 if (ec.ConstantCheckState)
369 res = checked (((LongConstant) left).Value +
370 ((LongConstant) right).Value);
371 else
372 res = unchecked (((LongConstant) left).Value +
373 ((LongConstant) right).Value);
375 result = new LongConstant (res, left.Location);
376 } else if (left is UIntConstant){
377 uint res;
379 if (ec.ConstantCheckState)
380 res = checked (((UIntConstant) left).Value +
381 ((UIntConstant) right).Value);
382 else
383 res = unchecked (((UIntConstant) left).Value +
384 ((UIntConstant) right).Value);
386 result = new UIntConstant (res, left.Location);
387 } else if (left is IntConstant){
388 int res;
390 if (ec.ConstantCheckState)
391 res = checked (((IntConstant) left).Value +
392 ((IntConstant) right).Value);
393 else
394 res = unchecked (((IntConstant) left).Value +
395 ((IntConstant) right).Value);
397 result = new IntConstant (res, left.Location);
398 } else if (left is DecimalConstant) {
399 decimal res;
401 if (ec.ConstantCheckState)
402 res = checked (((DecimalConstant) left).Value +
403 ((DecimalConstant) right).Value);
404 else
405 res = unchecked (((DecimalConstant) left).Value +
406 ((DecimalConstant) right).Value);
408 result = new DecimalConstant (res, left.Location);
410 } catch (OverflowException){
411 Error_CompileTimeOverflow (ec, loc);
414 return result;
416 case Binary.Operator.Subtraction:
418 // handle "E operator - (E x, U y)"
419 // handle "E operator - (Y y, E x)"
421 lc = left as EnumConstant;
422 rc = right as EnumConstant;
423 if (lc != null || rc != null){
424 if (lc == null) {
425 lc = rc;
426 lt = lc.Type;
427 right = left;
430 // U has to be implicitly convetible to E.base
431 right = right.ConvertImplicitly (ec, lc.Child.Type);
432 if (right == null)
433 return null;
435 result = BinaryFold (ec, oper, lc.Child, right, loc);
436 if (result == null)
437 return null;
439 result = result.Resolve (ec).TryReduce (ec, lt, loc);
440 if (result == null)
441 return null;
443 return new EnumConstant (result, lt);
446 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
447 return null;
449 try {
450 if (left is DoubleConstant){
451 double res;
453 if (ec.ConstantCheckState)
454 res = checked (((DoubleConstant) left).Value -
455 ((DoubleConstant) right).Value);
456 else
457 res = unchecked (((DoubleConstant) left).Value -
458 ((DoubleConstant) right).Value);
460 result = new DoubleConstant (res, left.Location);
461 } else if (left is FloatConstant){
462 float res;
464 if (ec.ConstantCheckState)
465 res = checked (((FloatConstant) left).Value -
466 ((FloatConstant) right).Value);
467 else
468 res = unchecked (((FloatConstant) left).Value -
469 ((FloatConstant) right).Value);
471 result = new FloatConstant (res, left.Location);
472 } else if (left is ULongConstant){
473 ulong res;
475 if (ec.ConstantCheckState)
476 res = checked (((ULongConstant) left).Value -
477 ((ULongConstant) right).Value);
478 else
479 res = unchecked (((ULongConstant) left).Value -
480 ((ULongConstant) right).Value);
482 result = new ULongConstant (res, left.Location);
483 } else if (left is LongConstant){
484 long res;
486 if (ec.ConstantCheckState)
487 res = checked (((LongConstant) left).Value -
488 ((LongConstant) right).Value);
489 else
490 res = unchecked (((LongConstant) left).Value -
491 ((LongConstant) right).Value);
493 result = new LongConstant (res, left.Location);
494 } else if (left is UIntConstant){
495 uint res;
497 if (ec.ConstantCheckState)
498 res = checked (((UIntConstant) left).Value -
499 ((UIntConstant) right).Value);
500 else
501 res = unchecked (((UIntConstant) left).Value -
502 ((UIntConstant) right).Value);
504 result = new UIntConstant (res, left.Location);
505 } else if (left is IntConstant){
506 int res;
508 if (ec.ConstantCheckState)
509 res = checked (((IntConstant) left).Value -
510 ((IntConstant) right).Value);
511 else
512 res = unchecked (((IntConstant) left).Value -
513 ((IntConstant) right).Value);
515 result = new IntConstant (res, left.Location);
516 } else if (left is DecimalConstant) {
517 decimal res;
519 if (ec.ConstantCheckState)
520 res = checked (((DecimalConstant) left).Value -
521 ((DecimalConstant) right).Value);
522 else
523 res = unchecked (((DecimalConstant) left).Value -
524 ((DecimalConstant) right).Value);
526 return new DecimalConstant (res, left.Location);
527 } else {
528 throw new Exception ( "Unexepected subtraction input: " + left);
530 } catch (OverflowException){
531 Error_CompileTimeOverflow (ec, loc);
534 return result;
536 case Binary.Operator.Multiply:
537 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
538 return null;
540 try {
541 if (left is DoubleConstant){
542 double res;
544 if (ec.ConstantCheckState)
545 res = checked (((DoubleConstant) left).Value *
546 ((DoubleConstant) right).Value);
547 else
548 res = unchecked (((DoubleConstant) left).Value *
549 ((DoubleConstant) right).Value);
551 return new DoubleConstant (res, left.Location);
552 } else if (left is FloatConstant){
553 float res;
555 if (ec.ConstantCheckState)
556 res = checked (((FloatConstant) left).Value *
557 ((FloatConstant) right).Value);
558 else
559 res = unchecked (((FloatConstant) left).Value *
560 ((FloatConstant) right).Value);
562 return new FloatConstant (res, left.Location);
563 } else if (left is ULongConstant){
564 ulong res;
566 if (ec.ConstantCheckState)
567 res = checked (((ULongConstant) left).Value *
568 ((ULongConstant) right).Value);
569 else
570 res = unchecked (((ULongConstant) left).Value *
571 ((ULongConstant) right).Value);
573 return new ULongConstant (res, left.Location);
574 } else if (left is LongConstant){
575 long res;
577 if (ec.ConstantCheckState)
578 res = checked (((LongConstant) left).Value *
579 ((LongConstant) right).Value);
580 else
581 res = unchecked (((LongConstant) left).Value *
582 ((LongConstant) right).Value);
584 return new LongConstant (res, left.Location);
585 } else if (left is UIntConstant){
586 uint res;
588 if (ec.ConstantCheckState)
589 res = checked (((UIntConstant) left).Value *
590 ((UIntConstant) right).Value);
591 else
592 res = unchecked (((UIntConstant) left).Value *
593 ((UIntConstant) right).Value);
595 return new UIntConstant (res, left.Location);
596 } else if (left is IntConstant){
597 int res;
599 if (ec.ConstantCheckState)
600 res = checked (((IntConstant) left).Value *
601 ((IntConstant) right).Value);
602 else
603 res = unchecked (((IntConstant) left).Value *
604 ((IntConstant) right).Value);
606 return new IntConstant (res, left.Location);
607 } else if (left is DecimalConstant) {
608 decimal res;
610 if (ec.ConstantCheckState)
611 res = checked (((DecimalConstant) left).Value *
612 ((DecimalConstant) right).Value);
613 else
614 res = unchecked (((DecimalConstant) left).Value *
615 ((DecimalConstant) right).Value);
617 return new DecimalConstant (res, left.Location);
618 } else {
619 throw new Exception ( "Unexepected multiply input: " + left);
621 } catch (OverflowException){
622 Error_CompileTimeOverflow (ec, loc);
624 break;
626 case Binary.Operator.Division:
627 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
628 return null;
630 try {
631 if (left is DoubleConstant){
632 double res;
634 if (ec.ConstantCheckState)
635 res = checked (((DoubleConstant) left).Value /
636 ((DoubleConstant) right).Value);
637 else
638 res = unchecked (((DoubleConstant) left).Value /
639 ((DoubleConstant) right).Value);
641 return new DoubleConstant (res, left.Location);
642 } else if (left is FloatConstant){
643 float res;
645 if (ec.ConstantCheckState)
646 res = checked (((FloatConstant) left).Value /
647 ((FloatConstant) right).Value);
648 else
649 res = unchecked (((FloatConstant) left).Value /
650 ((FloatConstant) right).Value);
652 return new FloatConstant (res, left.Location);
653 } else if (left is ULongConstant){
654 ulong res;
656 if (ec.ConstantCheckState)
657 res = checked (((ULongConstant) left).Value /
658 ((ULongConstant) right).Value);
659 else
660 res = unchecked (((ULongConstant) left).Value /
661 ((ULongConstant) right).Value);
663 return new ULongConstant (res, left.Location);
664 } else if (left is LongConstant){
665 long res;
667 if (ec.ConstantCheckState)
668 res = checked (((LongConstant) left).Value /
669 ((LongConstant) right).Value);
670 else
671 res = unchecked (((LongConstant) left).Value /
672 ((LongConstant) right).Value);
674 return new LongConstant (res, left.Location);
675 } else if (left is UIntConstant){
676 uint res;
678 if (ec.ConstantCheckState)
679 res = checked (((UIntConstant) left).Value /
680 ((UIntConstant) right).Value);
681 else
682 res = unchecked (((UIntConstant) left).Value /
683 ((UIntConstant) right).Value);
685 return new UIntConstant (res, left.Location);
686 } else if (left is IntConstant){
687 int res;
689 if (ec.ConstantCheckState)
690 res = checked (((IntConstant) left).Value /
691 ((IntConstant) right).Value);
692 else
693 res = unchecked (((IntConstant) left).Value /
694 ((IntConstant) right).Value);
696 return new IntConstant (res, left.Location);
697 } else if (left is DecimalConstant) {
698 decimal res;
700 if (ec.ConstantCheckState)
701 res = checked (((DecimalConstant) left).Value /
702 ((DecimalConstant) right).Value);
703 else
704 res = unchecked (((DecimalConstant) left).Value /
705 ((DecimalConstant) right).Value);
707 return new DecimalConstant (res, left.Location);
708 } else {
709 throw new Exception ( "Unexepected division input: " + left);
711 } catch (OverflowException){
712 Error_CompileTimeOverflow (ec, loc);
714 } catch (DivideByZeroException) {
715 ec.Report.Error (20, loc, "Division by constant zero");
718 break;
720 case Binary.Operator.Modulus:
721 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
722 return null;
724 try {
725 if (left is DoubleConstant){
726 double res;
728 if (ec.ConstantCheckState)
729 res = checked (((DoubleConstant) left).Value %
730 ((DoubleConstant) right).Value);
731 else
732 res = unchecked (((DoubleConstant) left).Value %
733 ((DoubleConstant) right).Value);
735 return new DoubleConstant (res, left.Location);
736 } else if (left is FloatConstant){
737 float res;
739 if (ec.ConstantCheckState)
740 res = checked (((FloatConstant) left).Value %
741 ((FloatConstant) right).Value);
742 else
743 res = unchecked (((FloatConstant) left).Value %
744 ((FloatConstant) right).Value);
746 return new FloatConstant (res, left.Location);
747 } else if (left is ULongConstant){
748 ulong res;
750 if (ec.ConstantCheckState)
751 res = checked (((ULongConstant) left).Value %
752 ((ULongConstant) right).Value);
753 else
754 res = unchecked (((ULongConstant) left).Value %
755 ((ULongConstant) right).Value);
757 return new ULongConstant (res, left.Location);
758 } else if (left is LongConstant){
759 long res;
761 if (ec.ConstantCheckState)
762 res = checked (((LongConstant) left).Value %
763 ((LongConstant) right).Value);
764 else
765 res = unchecked (((LongConstant) left).Value %
766 ((LongConstant) right).Value);
768 return new LongConstant (res, left.Location);
769 } else if (left is UIntConstant){
770 uint res;
772 if (ec.ConstantCheckState)
773 res = checked (((UIntConstant) left).Value %
774 ((UIntConstant) right).Value);
775 else
776 res = unchecked (((UIntConstant) left).Value %
777 ((UIntConstant) right).Value);
779 return new UIntConstant (res, left.Location);
780 } else if (left is IntConstant){
781 int res;
783 if (ec.ConstantCheckState)
784 res = checked (((IntConstant) left).Value %
785 ((IntConstant) right).Value);
786 else
787 res = unchecked (((IntConstant) left).Value %
788 ((IntConstant) right).Value);
790 return new IntConstant (res, left.Location);
791 } else {
792 throw new Exception ( "Unexepected modulus input: " + left);
794 } catch (DivideByZeroException){
795 ec.Report.Error (20, loc, "Division by constant zero");
796 } catch (OverflowException){
797 Error_CompileTimeOverflow (ec, loc);
799 break;
802 // There is no overflow checking on left shift
804 case Binary.Operator.LeftShift:
805 IntConstant ic = right.ConvertImplicitly (ec, TypeManager.int32_type) as IntConstant;
806 if (ic == null){
807 Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc);
808 return null;
811 int lshift_val = ic.Value;
812 if (left.Type == TypeManager.uint64_type)
813 return new ULongConstant (((ULongConstant)left).Value << lshift_val, left.Location);
814 if (left.Type == TypeManager.int64_type)
815 return new LongConstant (((LongConstant)left).Value << lshift_val, left.Location);
816 if (left.Type == TypeManager.uint32_type)
817 return new UIntConstant (((UIntConstant)left).Value << lshift_val, left.Location);
819 left = left.ConvertImplicitly (ec, TypeManager.int32_type);
820 if (left.Type == TypeManager.int32_type)
821 return new IntConstant (((IntConstant)left).Value << lshift_val, left.Location);
823 Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc);
824 break;
827 // There is no overflow checking on right shift
829 case Binary.Operator.RightShift:
830 IntConstant sic = right.ConvertImplicitly (ec, TypeManager.int32_type) as IntConstant;
831 if (sic == null){
832 Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); ;
833 return null;
835 int rshift_val = sic.Value;
836 if (left.Type == TypeManager.uint64_type)
837 return new ULongConstant (((ULongConstant)left).Value >> rshift_val, left.Location);
838 if (left.Type == TypeManager.int64_type)
839 return new LongConstant (((LongConstant)left).Value >> rshift_val, left.Location);
840 if (left.Type == TypeManager.uint32_type)
841 return new UIntConstant (((UIntConstant)left).Value >> rshift_val, left.Location);
843 left = left.ConvertImplicitly (ec, TypeManager.int32_type);
844 if (left.Type == TypeManager.int32_type)
845 return new IntConstant (((IntConstant)left).Value >> rshift_val, left.Location);
847 Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc);
848 break;
850 case Binary.Operator.Equality:
851 if (TypeManager.IsReferenceType (lt) && TypeManager.IsReferenceType (lt)) {
852 if (left.IsNull || right.IsNull) {
853 return ReducedExpression.Create (
854 new BoolConstant (left.IsNull == right.IsNull, left.Location).Resolve (ec),
855 new Binary (oper, left, right, loc));
858 if (left is StringConstant && right is StringConstant)
859 return new BoolConstant (
860 ((StringConstant) left).Value == ((StringConstant) right).Value, left.Location);
862 return null;
865 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
866 return null;
868 bool_res = false;
869 if (left is DoubleConstant)
870 bool_res = ((DoubleConstant) left).Value ==
871 ((DoubleConstant) right).Value;
872 else if (left is FloatConstant)
873 bool_res = ((FloatConstant) left).Value ==
874 ((FloatConstant) right).Value;
875 else if (left is ULongConstant)
876 bool_res = ((ULongConstant) left).Value ==
877 ((ULongConstant) right).Value;
878 else if (left is LongConstant)
879 bool_res = ((LongConstant) left).Value ==
880 ((LongConstant) right).Value;
881 else if (left is UIntConstant)
882 bool_res = ((UIntConstant) left).Value ==
883 ((UIntConstant) right).Value;
884 else if (left is IntConstant)
885 bool_res = ((IntConstant) left).Value ==
886 ((IntConstant) right).Value;
887 else
888 return null;
890 return new BoolConstant (bool_res, left.Location);
892 case Binary.Operator.Inequality:
893 if (TypeManager.IsReferenceType (lt) && TypeManager.IsReferenceType (lt)) {
894 if (left.IsNull || right.IsNull) {
895 return ReducedExpression.Create (
896 new BoolConstant (left.IsNull != right.IsNull, left.Location).Resolve (ec),
897 new Binary (oper, left, right, loc));
900 if (left is StringConstant && right is StringConstant)
901 return new BoolConstant (
902 ((StringConstant) left).Value != ((StringConstant) right).Value, left.Location);
904 return null;
907 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
908 return null;
910 bool_res = false;
911 if (left is DoubleConstant)
912 bool_res = ((DoubleConstant) left).Value !=
913 ((DoubleConstant) right).Value;
914 else if (left is FloatConstant)
915 bool_res = ((FloatConstant) left).Value !=
916 ((FloatConstant) right).Value;
917 else if (left is ULongConstant)
918 bool_res = ((ULongConstant) left).Value !=
919 ((ULongConstant) right).Value;
920 else if (left is LongConstant)
921 bool_res = ((LongConstant) left).Value !=
922 ((LongConstant) right).Value;
923 else if (left is UIntConstant)
924 bool_res = ((UIntConstant) left).Value !=
925 ((UIntConstant) right).Value;
926 else if (left is IntConstant)
927 bool_res = ((IntConstant) left).Value !=
928 ((IntConstant) right).Value;
929 else
930 return null;
932 return new BoolConstant (bool_res, left.Location);
934 case Binary.Operator.LessThan:
935 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
936 return null;
938 bool_res = false;
939 if (left is DoubleConstant)
940 bool_res = ((DoubleConstant) left).Value <
941 ((DoubleConstant) right).Value;
942 else if (left is FloatConstant)
943 bool_res = ((FloatConstant) left).Value <
944 ((FloatConstant) right).Value;
945 else if (left is ULongConstant)
946 bool_res = ((ULongConstant) left).Value <
947 ((ULongConstant) right).Value;
948 else if (left is LongConstant)
949 bool_res = ((LongConstant) left).Value <
950 ((LongConstant) right).Value;
951 else if (left is UIntConstant)
952 bool_res = ((UIntConstant) left).Value <
953 ((UIntConstant) right).Value;
954 else if (left is IntConstant)
955 bool_res = ((IntConstant) left).Value <
956 ((IntConstant) right).Value;
957 else
958 return null;
960 return new BoolConstant (bool_res, left.Location);
962 case Binary.Operator.GreaterThan:
963 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
964 return null;
966 bool_res = false;
967 if (left is DoubleConstant)
968 bool_res = ((DoubleConstant) left).Value >
969 ((DoubleConstant) right).Value;
970 else if (left is FloatConstant)
971 bool_res = ((FloatConstant) left).Value >
972 ((FloatConstant) right).Value;
973 else if (left is ULongConstant)
974 bool_res = ((ULongConstant) left).Value >
975 ((ULongConstant) right).Value;
976 else if (left is LongConstant)
977 bool_res = ((LongConstant) left).Value >
978 ((LongConstant) right).Value;
979 else if (left is UIntConstant)
980 bool_res = ((UIntConstant) left).Value >
981 ((UIntConstant) right).Value;
982 else if (left is IntConstant)
983 bool_res = ((IntConstant) left).Value >
984 ((IntConstant) right).Value;
985 else
986 return null;
988 return new BoolConstant (bool_res, left.Location);
990 case Binary.Operator.GreaterThanOrEqual:
991 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
992 return null;
994 bool_res = false;
995 if (left is DoubleConstant)
996 bool_res = ((DoubleConstant) left).Value >=
997 ((DoubleConstant) right).Value;
998 else if (left is FloatConstant)
999 bool_res = ((FloatConstant) left).Value >=
1000 ((FloatConstant) right).Value;
1001 else if (left is ULongConstant)
1002 bool_res = ((ULongConstant) left).Value >=
1003 ((ULongConstant) right).Value;
1004 else if (left is LongConstant)
1005 bool_res = ((LongConstant) left).Value >=
1006 ((LongConstant) right).Value;
1007 else if (left is UIntConstant)
1008 bool_res = ((UIntConstant) left).Value >=
1009 ((UIntConstant) right).Value;
1010 else if (left is IntConstant)
1011 bool_res = ((IntConstant) left).Value >=
1012 ((IntConstant) right).Value;
1013 else
1014 return null;
1016 return new BoolConstant (bool_res, left.Location);
1018 case Binary.Operator.LessThanOrEqual:
1019 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
1020 return null;
1022 bool_res = false;
1023 if (left is DoubleConstant)
1024 bool_res = ((DoubleConstant) left).Value <=
1025 ((DoubleConstant) right).Value;
1026 else if (left is FloatConstant)
1027 bool_res = ((FloatConstant) left).Value <=
1028 ((FloatConstant) right).Value;
1029 else if (left is ULongConstant)
1030 bool_res = ((ULongConstant) left).Value <=
1031 ((ULongConstant) right).Value;
1032 else if (left is LongConstant)
1033 bool_res = ((LongConstant) left).Value <=
1034 ((LongConstant) right).Value;
1035 else if (left is UIntConstant)
1036 bool_res = ((UIntConstant) left).Value <=
1037 ((UIntConstant) right).Value;
1038 else if (left is IntConstant)
1039 bool_res = ((IntConstant) left).Value <=
1040 ((IntConstant) right).Value;
1041 else
1042 return null;
1044 return new BoolConstant (bool_res, left.Location);
1047 return null;