2 // cfold.cs: Constant Folding
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
8 // Copyright 2002, 2003 Ximian, Inc.
9 // Copyright 2003-2008, Novell, Inc.
13 namespace Mono.CSharp {
15 public class ConstantFold {
17 static TypeSpec[] binary_promotions;
19 public static TypeSpec[] BinaryPromotionsTypes {
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
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) {
53 return t == rtype || ConvertPromotion (rc, ref right, ref left, t);
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);
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;
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");
88 /// Constant expression folder for binary operations.
90 /// Returns null if the expression can not be folded.
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);
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);
114 return new SideEffectConstant (result, right, loc);
117 TypeSpec lt = left.Type;
118 TypeSpec rt = right.Type;
121 if (lt == TypeManager.bool_type && lt == rt) {
122 bool lv = (bool) left.GetValue ();
123 bool rv = (bool) right.GetValue ();
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);
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) {
154 /// E operator |(E x, E y);
155 /// E operator &(E x, E y);
156 /// E operator ^(E x, E y);
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);
163 result = result.Resolve (ec).TryReduce (ec, lt, loc);
167 /// U operator -(E x, E y);
169 case Binary.Operator.Subtraction:
170 result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
172 result = result.Resolve (ec).TryReduce (ec, EnumSpec.GetUnderlyingType (lt), loc);
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);
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);
195 case Binary.Operator.BitwiseOr:
197 // bool? operator &(bool? x, bool? y);
199 if ((lt == TypeManager.bool_type && right is NullLiteral) ||
200 (rt == TypeManager.bool_type && left is NullLiteral)) {
201 var b = new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec);
203 // false | null => null
204 // null | false => null
205 if ((right is NullLiteral && left.IsDefaultValue) || (left is NullLiteral && right.IsDefaultValue))
206 return Nullable.LiftedNull.CreateFromExpression (ec, b);
208 // true | null => true
209 // null | true => true
210 return ReducedExpression.Create (new BoolConstant (true, loc).Resolve (ec), b);
213 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
216 if (left is IntConstant){
217 int res = ((IntConstant) left).Value | ((IntConstant) right).Value;
219 return new IntConstant (res, left.Location);
221 if (left is UIntConstant){
222 uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value;
224 return new UIntConstant (res, left.Location);
226 if (left is LongConstant){
227 long res = ((LongConstant)left).Value | ((LongConstant)right).Value;
229 return new LongConstant (res, left.Location);
231 if (left is ULongConstant){
232 ulong res = ((ULongConstant)left).Value |
233 ((ULongConstant)right).Value;
235 return new ULongConstant (res, left.Location);
239 case Binary.Operator.BitwiseAnd:
241 // bool? operator &(bool? x, bool? y);
243 if ((lt == TypeManager.bool_type && right is NullLiteral) ||
244 (rt == TypeManager.bool_type && left is NullLiteral)) {
245 var b = new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec);
247 // false & null => false
248 // null & false => false
249 if ((right is NullLiteral && left.IsDefaultValue) || (left is NullLiteral && right.IsDefaultValue))
250 return ReducedExpression.Create (new BoolConstant (false, loc).Resolve (ec), b);
252 // true & null => null
253 // null & true => null
254 return Nullable.LiftedNull.CreateFromExpression (ec, b);
257 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
261 /// int operator &(int x, int y);
262 /// uint operator &(uint x, uint y);
263 /// long operator &(long x, long y);
264 /// ulong operator &(ulong x, ulong y);
266 if (left is IntConstant){
267 int res = ((IntConstant) left).Value & ((IntConstant) right).Value;
268 return new IntConstant (res, left.Location);
270 if (left is UIntConstant){
271 uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value;
272 return new UIntConstant (res, left.Location);
274 if (left is LongConstant){
275 long res = ((LongConstant)left).Value & ((LongConstant)right).Value;
276 return new LongConstant (res, left.Location);
278 if (left is ULongConstant){
279 ulong res = ((ULongConstant)left).Value &
280 ((ULongConstant)right).Value;
282 return new ULongConstant (res, left.Location);
286 case Binary.Operator.ExclusiveOr:
287 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
290 if (left is IntConstant){
291 int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value;
292 return new IntConstant (res, left.Location);
294 if (left is UIntConstant){
295 uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value;
297 return new UIntConstant (res, left.Location);
299 if (left is LongConstant){
300 long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value;
302 return new LongConstant (res, left.Location);
304 if (left is ULongConstant){
305 ulong res = ((ULongConstant)left).Value ^
306 ((ULongConstant)right).Value;
308 return new ULongConstant (res, left.Location);
312 case Binary.Operator.Addition:
313 if (lt == InternalType.Null)
316 if (rt == InternalType.Null)
320 // If both sides are strings, then concatenate, if
321 // one is a string, and the other is not, then defer
322 // to runtime concatenation
324 if (lt == TypeManager.string_type || rt == TypeManager.string_type){
326 return new StringConstant ((string)left.GetValue () + (string)right.GetValue (),
333 // handle "E operator + (E x, U y)"
334 // handle "E operator + (Y y, E x)"
336 EnumConstant lc = left as EnumConstant;
337 EnumConstant rc = right as EnumConstant;
338 if (lc != null || rc != null){
345 // U has to be implicitly convetible to E.base
346 right = right.ConvertImplicitly (ec, lc.Child.Type);
350 result = BinaryFold (ec, oper, lc.Child, right, loc);
354 result = result.Resolve (ec).TryReduce (ec, lt, loc);
358 return new EnumConstant (result, lt);
361 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
365 if (left is DoubleConstant){
368 if (ec.ConstantCheckState)
369 res = checked (((DoubleConstant) left).Value +
370 ((DoubleConstant) right).Value);
372 res = unchecked (((DoubleConstant) left).Value +
373 ((DoubleConstant) right).Value);
375 return new DoubleConstant (res, left.Location);
377 if (left is FloatConstant){
380 if (ec.ConstantCheckState)
381 res = checked (((FloatConstant) left).Value +
382 ((FloatConstant) right).Value);
384 res = unchecked (((FloatConstant) left).Value +
385 ((FloatConstant) right).Value);
387 result = new FloatConstant (res, left.Location);
388 } else if (left is ULongConstant){
391 if (ec.ConstantCheckState)
392 res = checked (((ULongConstant) left).Value +
393 ((ULongConstant) right).Value);
395 res = unchecked (((ULongConstant) left).Value +
396 ((ULongConstant) right).Value);
398 result = new ULongConstant (res, left.Location);
399 } else if (left is LongConstant){
402 if (ec.ConstantCheckState)
403 res = checked (((LongConstant) left).Value +
404 ((LongConstant) right).Value);
406 res = unchecked (((LongConstant) left).Value +
407 ((LongConstant) right).Value);
409 result = new LongConstant (res, left.Location);
410 } else if (left is UIntConstant){
413 if (ec.ConstantCheckState)
414 res = checked (((UIntConstant) left).Value +
415 ((UIntConstant) right).Value);
417 res = unchecked (((UIntConstant) left).Value +
418 ((UIntConstant) right).Value);
420 result = new UIntConstant (res, left.Location);
421 } else if (left is IntConstant){
424 if (ec.ConstantCheckState)
425 res = checked (((IntConstant) left).Value +
426 ((IntConstant) right).Value);
428 res = unchecked (((IntConstant) left).Value +
429 ((IntConstant) right).Value);
431 result = new IntConstant (res, left.Location);
432 } else if (left is DecimalConstant) {
435 if (ec.ConstantCheckState)
436 res = checked (((DecimalConstant) left).Value +
437 ((DecimalConstant) right).Value);
439 res = unchecked (((DecimalConstant) left).Value +
440 ((DecimalConstant) right).Value);
442 result = new DecimalConstant (res, left.Location);
444 } catch (OverflowException){
445 Error_CompileTimeOverflow (ec, loc);
450 case Binary.Operator.Subtraction:
452 // handle "E operator - (E x, U y)"
453 // handle "E operator - (Y y, E x)"
455 lc = left as EnumConstant;
456 rc = right as EnumConstant;
457 if (lc != null || rc != null){
464 // U has to be implicitly convetible to E.base
465 right = right.ConvertImplicitly (ec, lc.Child.Type);
469 result = BinaryFold (ec, oper, lc.Child, right, loc);
473 result = result.Resolve (ec).TryReduce (ec, lt, loc);
477 return new EnumConstant (result, lt);
480 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
484 if (left is DoubleConstant){
487 if (ec.ConstantCheckState)
488 res = checked (((DoubleConstant) left).Value -
489 ((DoubleConstant) right).Value);
491 res = unchecked (((DoubleConstant) left).Value -
492 ((DoubleConstant) right).Value);
494 result = new DoubleConstant (res, left.Location);
495 } else if (left is FloatConstant){
498 if (ec.ConstantCheckState)
499 res = checked (((FloatConstant) left).Value -
500 ((FloatConstant) right).Value);
502 res = unchecked (((FloatConstant) left).Value -
503 ((FloatConstant) right).Value);
505 result = new FloatConstant (res, left.Location);
506 } else if (left is ULongConstant){
509 if (ec.ConstantCheckState)
510 res = checked (((ULongConstant) left).Value -
511 ((ULongConstant) right).Value);
513 res = unchecked (((ULongConstant) left).Value -
514 ((ULongConstant) right).Value);
516 result = new ULongConstant (res, left.Location);
517 } else if (left is LongConstant){
520 if (ec.ConstantCheckState)
521 res = checked (((LongConstant) left).Value -
522 ((LongConstant) right).Value);
524 res = unchecked (((LongConstant) left).Value -
525 ((LongConstant) right).Value);
527 result = new LongConstant (res, left.Location);
528 } else if (left is UIntConstant){
531 if (ec.ConstantCheckState)
532 res = checked (((UIntConstant) left).Value -
533 ((UIntConstant) right).Value);
535 res = unchecked (((UIntConstant) left).Value -
536 ((UIntConstant) right).Value);
538 result = new UIntConstant (res, left.Location);
539 } else if (left is IntConstant){
542 if (ec.ConstantCheckState)
543 res = checked (((IntConstant) left).Value -
544 ((IntConstant) right).Value);
546 res = unchecked (((IntConstant) left).Value -
547 ((IntConstant) right).Value);
549 result = new IntConstant (res, left.Location);
550 } else if (left is DecimalConstant) {
553 if (ec.ConstantCheckState)
554 res = checked (((DecimalConstant) left).Value -
555 ((DecimalConstant) right).Value);
557 res = unchecked (((DecimalConstant) left).Value -
558 ((DecimalConstant) right).Value);
560 return new DecimalConstant (res, left.Location);
562 throw new Exception ( "Unexepected subtraction input: " + left);
564 } catch (OverflowException){
565 Error_CompileTimeOverflow (ec, loc);
570 case Binary.Operator.Multiply:
571 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
575 if (left is DoubleConstant){
578 if (ec.ConstantCheckState)
579 res = checked (((DoubleConstant) left).Value *
580 ((DoubleConstant) right).Value);
582 res = unchecked (((DoubleConstant) left).Value *
583 ((DoubleConstant) right).Value);
585 return new DoubleConstant (res, left.Location);
586 } else if (left is FloatConstant){
589 if (ec.ConstantCheckState)
590 res = checked (((FloatConstant) left).Value *
591 ((FloatConstant) right).Value);
593 res = unchecked (((FloatConstant) left).Value *
594 ((FloatConstant) right).Value);
596 return new FloatConstant (res, left.Location);
597 } else if (left is ULongConstant){
600 if (ec.ConstantCheckState)
601 res = checked (((ULongConstant) left).Value *
602 ((ULongConstant) right).Value);
604 res = unchecked (((ULongConstant) left).Value *
605 ((ULongConstant) right).Value);
607 return new ULongConstant (res, left.Location);
608 } else if (left is LongConstant){
611 if (ec.ConstantCheckState)
612 res = checked (((LongConstant) left).Value *
613 ((LongConstant) right).Value);
615 res = unchecked (((LongConstant) left).Value *
616 ((LongConstant) right).Value);
618 return new LongConstant (res, left.Location);
619 } else if (left is UIntConstant){
622 if (ec.ConstantCheckState)
623 res = checked (((UIntConstant) left).Value *
624 ((UIntConstant) right).Value);
626 res = unchecked (((UIntConstant) left).Value *
627 ((UIntConstant) right).Value);
629 return new UIntConstant (res, left.Location);
630 } else if (left is IntConstant){
633 if (ec.ConstantCheckState)
634 res = checked (((IntConstant) left).Value *
635 ((IntConstant) right).Value);
637 res = unchecked (((IntConstant) left).Value *
638 ((IntConstant) right).Value);
640 return new IntConstant (res, left.Location);
641 } else if (left is DecimalConstant) {
644 if (ec.ConstantCheckState)
645 res = checked (((DecimalConstant) left).Value *
646 ((DecimalConstant) right).Value);
648 res = unchecked (((DecimalConstant) left).Value *
649 ((DecimalConstant) right).Value);
651 return new DecimalConstant (res, left.Location);
653 throw new Exception ( "Unexepected multiply input: " + left);
655 } catch (OverflowException){
656 Error_CompileTimeOverflow (ec, loc);
660 case Binary.Operator.Division:
661 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
665 if (left is DoubleConstant){
668 if (ec.ConstantCheckState)
669 res = checked (((DoubleConstant) left).Value /
670 ((DoubleConstant) right).Value);
672 res = unchecked (((DoubleConstant) left).Value /
673 ((DoubleConstant) right).Value);
675 return new DoubleConstant (res, left.Location);
676 } else if (left is FloatConstant){
679 if (ec.ConstantCheckState)
680 res = checked (((FloatConstant) left).Value /
681 ((FloatConstant) right).Value);
683 res = unchecked (((FloatConstant) left).Value /
684 ((FloatConstant) right).Value);
686 return new FloatConstant (res, left.Location);
687 } else if (left is ULongConstant){
690 if (ec.ConstantCheckState)
691 res = checked (((ULongConstant) left).Value /
692 ((ULongConstant) right).Value);
694 res = unchecked (((ULongConstant) left).Value /
695 ((ULongConstant) right).Value);
697 return new ULongConstant (res, left.Location);
698 } else if (left is LongConstant){
701 if (ec.ConstantCheckState)
702 res = checked (((LongConstant) left).Value /
703 ((LongConstant) right).Value);
705 res = unchecked (((LongConstant) left).Value /
706 ((LongConstant) right).Value);
708 return new LongConstant (res, left.Location);
709 } else if (left is UIntConstant){
712 if (ec.ConstantCheckState)
713 res = checked (((UIntConstant) left).Value /
714 ((UIntConstant) right).Value);
716 res = unchecked (((UIntConstant) left).Value /
717 ((UIntConstant) right).Value);
719 return new UIntConstant (res, left.Location);
720 } else if (left is IntConstant){
723 if (ec.ConstantCheckState)
724 res = checked (((IntConstant) left).Value /
725 ((IntConstant) right).Value);
727 res = unchecked (((IntConstant) left).Value /
728 ((IntConstant) right).Value);
730 return new IntConstant (res, left.Location);
731 } else if (left is DecimalConstant) {
734 if (ec.ConstantCheckState)
735 res = checked (((DecimalConstant) left).Value /
736 ((DecimalConstant) right).Value);
738 res = unchecked (((DecimalConstant) left).Value /
739 ((DecimalConstant) right).Value);
741 return new DecimalConstant (res, left.Location);
743 throw new Exception ( "Unexepected division input: " + left);
745 } catch (OverflowException){
746 Error_CompileTimeOverflow (ec, loc);
748 } catch (DivideByZeroException) {
749 ec.Report.Error (20, loc, "Division by constant zero");
754 case Binary.Operator.Modulus:
755 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
759 if (left is DoubleConstant){
762 if (ec.ConstantCheckState)
763 res = checked (((DoubleConstant) left).Value %
764 ((DoubleConstant) right).Value);
766 res = unchecked (((DoubleConstant) left).Value %
767 ((DoubleConstant) right).Value);
769 return new DoubleConstant (res, left.Location);
770 } else if (left is FloatConstant){
773 if (ec.ConstantCheckState)
774 res = checked (((FloatConstant) left).Value %
775 ((FloatConstant) right).Value);
777 res = unchecked (((FloatConstant) left).Value %
778 ((FloatConstant) right).Value);
780 return new FloatConstant (res, left.Location);
781 } else if (left is ULongConstant){
784 if (ec.ConstantCheckState)
785 res = checked (((ULongConstant) left).Value %
786 ((ULongConstant) right).Value);
788 res = unchecked (((ULongConstant) left).Value %
789 ((ULongConstant) right).Value);
791 return new ULongConstant (res, left.Location);
792 } else if (left is LongConstant){
795 if (ec.ConstantCheckState)
796 res = checked (((LongConstant) left).Value %
797 ((LongConstant) right).Value);
799 res = unchecked (((LongConstant) left).Value %
800 ((LongConstant) right).Value);
802 return new LongConstant (res, left.Location);
803 } else if (left is UIntConstant){
806 if (ec.ConstantCheckState)
807 res = checked (((UIntConstant) left).Value %
808 ((UIntConstant) right).Value);
810 res = unchecked (((UIntConstant) left).Value %
811 ((UIntConstant) right).Value);
813 return new UIntConstant (res, left.Location);
814 } else if (left is IntConstant){
817 if (ec.ConstantCheckState)
818 res = checked (((IntConstant) left).Value %
819 ((IntConstant) right).Value);
821 res = unchecked (((IntConstant) left).Value %
822 ((IntConstant) right).Value);
824 return new IntConstant (res, left.Location);
826 throw new Exception ( "Unexepected modulus input: " + left);
828 } catch (DivideByZeroException){
829 ec.Report.Error (20, loc, "Division by constant zero");
830 } catch (OverflowException){
831 Error_CompileTimeOverflow (ec, loc);
836 // There is no overflow checking on left shift
838 case Binary.Operator.LeftShift:
839 IntConstant ic = right.ConvertImplicitly (ec, TypeManager.int32_type) as IntConstant;
841 Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc);
845 int lshift_val = ic.Value;
846 if (left.Type == TypeManager.uint64_type)
847 return new ULongConstant (((ULongConstant)left).Value << lshift_val, left.Location);
848 if (left.Type == TypeManager.int64_type)
849 return new LongConstant (((LongConstant)left).Value << lshift_val, left.Location);
850 if (left.Type == TypeManager.uint32_type)
851 return new UIntConstant (((UIntConstant)left).Value << lshift_val, left.Location);
853 // null << value => null
854 if (left is NullLiteral)
855 return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec);
857 left = left.ConvertImplicitly (ec, TypeManager.int32_type);
858 if (left.Type == TypeManager.int32_type)
859 return new IntConstant (((IntConstant)left).Value << lshift_val, left.Location);
861 Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc);
865 // There is no overflow checking on right shift
867 case Binary.Operator.RightShift:
868 IntConstant sic = right.ConvertImplicitly (ec, TypeManager.int32_type) as IntConstant;
870 Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); ;
873 int rshift_val = sic.Value;
874 if (left.Type == TypeManager.uint64_type)
875 return new ULongConstant (((ULongConstant)left).Value >> rshift_val, left.Location);
876 if (left.Type == TypeManager.int64_type)
877 return new LongConstant (((LongConstant)left).Value >> rshift_val, left.Location);
878 if (left.Type == TypeManager.uint32_type)
879 return new UIntConstant (((UIntConstant)left).Value >> rshift_val, left.Location);
881 // null >> value => null
882 if (left is NullLiteral)
883 return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec);
885 left = left.ConvertImplicitly (ec, TypeManager.int32_type);
886 if (left.Type == TypeManager.int32_type)
887 return new IntConstant (((IntConstant)left).Value >> rshift_val, left.Location);
889 Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc);
892 case Binary.Operator.Equality:
893 if (TypeManager.IsReferenceType (lt) && TypeManager.IsReferenceType (rt) ||
894 (left is Nullable.LiftedNull && right.IsNull) ||
895 (right is Nullable.LiftedNull && left.IsNull)) {
896 if (left.IsNull || right.IsNull) {
897 return ReducedExpression.Create (
898 new BoolConstant (left.IsNull == right.IsNull, left.Location).Resolve (ec),
899 new Binary (oper, left, right, loc));
902 if (left is StringConstant && right is StringConstant)
903 return new BoolConstant (
904 ((StringConstant) left).Value == ((StringConstant) right).Value, left.Location);
909 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
913 if (left is DoubleConstant)
914 bool_res = ((DoubleConstant) left).Value ==
915 ((DoubleConstant) right).Value;
916 else if (left is FloatConstant)
917 bool_res = ((FloatConstant) left).Value ==
918 ((FloatConstant) right).Value;
919 else if (left is ULongConstant)
920 bool_res = ((ULongConstant) left).Value ==
921 ((ULongConstant) right).Value;
922 else if (left is LongConstant)
923 bool_res = ((LongConstant) left).Value ==
924 ((LongConstant) right).Value;
925 else if (left is UIntConstant)
926 bool_res = ((UIntConstant) left).Value ==
927 ((UIntConstant) right).Value;
928 else if (left is IntConstant)
929 bool_res = ((IntConstant) left).Value ==
930 ((IntConstant) right).Value;
934 return new BoolConstant (bool_res, left.Location);
936 case Binary.Operator.Inequality:
937 if (TypeManager.IsReferenceType (lt) && TypeManager.IsReferenceType (rt) ||
938 (left is Nullable.LiftedNull && right.IsNull) ||
939 (right is Nullable.LiftedNull && left.IsNull)) {
940 if (left.IsNull || right.IsNull) {
941 return ReducedExpression.Create (
942 new BoolConstant (left.IsNull != right.IsNull, left.Location).Resolve (ec),
943 new Binary (oper, left, right, loc));
946 if (left is StringConstant && right is StringConstant)
947 return new BoolConstant (
948 ((StringConstant) left).Value != ((StringConstant) right).Value, left.Location);
953 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
957 if (left is DoubleConstant)
958 bool_res = ((DoubleConstant) left).Value !=
959 ((DoubleConstant) right).Value;
960 else if (left is FloatConstant)
961 bool_res = ((FloatConstant) left).Value !=
962 ((FloatConstant) right).Value;
963 else if (left is ULongConstant)
964 bool_res = ((ULongConstant) left).Value !=
965 ((ULongConstant) right).Value;
966 else if (left is LongConstant)
967 bool_res = ((LongConstant) left).Value !=
968 ((LongConstant) right).Value;
969 else if (left is UIntConstant)
970 bool_res = ((UIntConstant) left).Value !=
971 ((UIntConstant) right).Value;
972 else if (left is IntConstant)
973 bool_res = ((IntConstant) left).Value !=
974 ((IntConstant) right).Value;
978 return new BoolConstant (bool_res, left.Location);
980 case Binary.Operator.LessThan:
981 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
985 if (left is DoubleConstant)
986 bool_res = ((DoubleConstant) left).Value <
987 ((DoubleConstant) right).Value;
988 else if (left is FloatConstant)
989 bool_res = ((FloatConstant) left).Value <
990 ((FloatConstant) right).Value;
991 else if (left is ULongConstant)
992 bool_res = ((ULongConstant) left).Value <
993 ((ULongConstant) right).Value;
994 else if (left is LongConstant)
995 bool_res = ((LongConstant) left).Value <
996 ((LongConstant) right).Value;
997 else if (left is UIntConstant)
998 bool_res = ((UIntConstant) left).Value <
999 ((UIntConstant) right).Value;
1000 else if (left is IntConstant)
1001 bool_res = ((IntConstant) left).Value <
1002 ((IntConstant) right).Value;
1006 return new BoolConstant (bool_res, left.Location);
1008 case Binary.Operator.GreaterThan:
1009 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
1013 if (left is DoubleConstant)
1014 bool_res = ((DoubleConstant) left).Value >
1015 ((DoubleConstant) right).Value;
1016 else if (left is FloatConstant)
1017 bool_res = ((FloatConstant) left).Value >
1018 ((FloatConstant) right).Value;
1019 else if (left is ULongConstant)
1020 bool_res = ((ULongConstant) left).Value >
1021 ((ULongConstant) right).Value;
1022 else if (left is LongConstant)
1023 bool_res = ((LongConstant) left).Value >
1024 ((LongConstant) right).Value;
1025 else if (left is UIntConstant)
1026 bool_res = ((UIntConstant) left).Value >
1027 ((UIntConstant) right).Value;
1028 else if (left is IntConstant)
1029 bool_res = ((IntConstant) left).Value >
1030 ((IntConstant) right).Value;
1034 return new BoolConstant (bool_res, left.Location);
1036 case Binary.Operator.GreaterThanOrEqual:
1037 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
1041 if (left is DoubleConstant)
1042 bool_res = ((DoubleConstant) left).Value >=
1043 ((DoubleConstant) right).Value;
1044 else if (left is FloatConstant)
1045 bool_res = ((FloatConstant) left).Value >=
1046 ((FloatConstant) right).Value;
1047 else if (left is ULongConstant)
1048 bool_res = ((ULongConstant) left).Value >=
1049 ((ULongConstant) right).Value;
1050 else if (left is LongConstant)
1051 bool_res = ((LongConstant) left).Value >=
1052 ((LongConstant) right).Value;
1053 else if (left is UIntConstant)
1054 bool_res = ((UIntConstant) left).Value >=
1055 ((UIntConstant) right).Value;
1056 else if (left is IntConstant)
1057 bool_res = ((IntConstant) left).Value >=
1058 ((IntConstant) right).Value;
1062 return new BoolConstant (bool_res, left.Location);
1064 case Binary.Operator.LessThanOrEqual:
1065 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
1069 if (left is DoubleConstant)
1070 bool_res = ((DoubleConstant) left).Value <=
1071 ((DoubleConstant) right).Value;
1072 else if (left is FloatConstant)
1073 bool_res = ((FloatConstant) left).Value <=
1074 ((FloatConstant) right).Value;
1075 else if (left is ULongConstant)
1076 bool_res = ((ULongConstant) left).Value <=
1077 ((ULongConstant) right).Value;
1078 else if (left is LongConstant)
1079 bool_res = ((LongConstant) left).Value <=
1080 ((LongConstant) right).Value;
1081 else if (left is UIntConstant)
1082 bool_res = ((UIntConstant) left).Value <=
1083 ((UIntConstant) right).Value;
1084 else if (left is IntConstant)
1085 bool_res = ((IntConstant) left).Value <=
1086 ((IntConstant) right).Value;
1090 return new BoolConstant (bool_res, left.Location);