2 // cfold.cs: Constant Folding
5 // Miguel de Icaza (miguel@ximian.com)
7 // (C) 2002, 2003 Ximian, Inc.
12 namespace Mono.CSharp {
14 public class ConstantFold {
17 // Performs the numeric promotions on the left and right expresions
18 // and desposits the results on `lc' and `rc'.
20 // On success, the types of `lc' and `rc' on output will always match,
21 // and the pair will be one of:
29 // (short, short) (Happens with enumerations with underlying short type)
30 // (ushort, ushort) (Happens with enumerations with underlying short type)
32 static void DoConstantNumericPromotions (EmitContext ec, Binary.Operator oper,
33 ref Constant left, ref Constant right,
36 if (left is DoubleConstant || right is DoubleConstant){
38 // If either side is a double, convert the other to a double
40 if (!(left is DoubleConstant))
41 left = left.ToDouble (loc);
43 if (!(right is DoubleConstant))
44 right = right.ToDouble (loc);
46 } else if (left is FloatConstant || right is FloatConstant) {
48 // If either side is a float, convert the other to a float
50 if (!(left is FloatConstant))
51 left = left.ToFloat (loc);
53 if (!(right is FloatConstant))
54 right = right.ToFloat (loc);
56 } else if (left is ULongConstant || right is ULongConstant){
58 // If either operand is of type ulong, the other operand is
59 // converted to type ulong. or an error ocurrs if the other
60 // operand is of type sbyte, short, int or long
63 Constant match, other;
66 if (left is ULongConstant){
71 if (!(right is ULongConstant))
72 right = right.ToULong (loc);
78 left = left.ToULong (loc);
82 if (other is SByteConstant || other is ShortConstant ||
83 other is IntConstant || other is LongConstant){
84 Binary.Error_OperatorAmbiguous
85 (loc, oper, other.Type, match.Type);
91 } else if (left is LongConstant || right is LongConstant){
93 // If either operand is of type long, the other operand is converted
96 if (!(left is LongConstant))
97 left = left.ToLong (loc);
98 else if (!(right is LongConstant))
99 right = right.ToLong (loc);
101 } else if (left is UIntConstant || right is UIntConstant){
103 // If either operand is of type uint, and the other
104 // operand is of type sbyte, short or int, the operands are
105 // converted to type long.
108 if (left is UIntConstant)
114 if (other is UIntConstant)
117 IntConstant ic = other as IntConstant;
121 left = new UIntConstant ((uint) ic.Value, ic.Location);
123 right = new UIntConstant ((uint) ic.Value, ic.Location);
128 if (other is SByteConstant || other is ShortConstant || ic != null){
129 left = left.ToLong (loc);
130 right = right.ToLong (loc);
132 left = left.ToUInt (loc);
133 right = left.ToUInt (loc);
137 } else if (left is DecimalConstant || right is DecimalConstant) {
138 if (!(left is DecimalConstant))
139 left = left.ToDecimal (loc);
140 else if (!(right is DecimalConstant))
141 right = right.ToDecimal (loc);
143 } else if (left is EnumConstant || right is EnumConstant){
144 if (left is EnumConstant)
145 left = ((EnumConstant) left).Child;
146 if (right is EnumConstant)
147 right = ((EnumConstant) right).Child;
149 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
154 // Force conversions to int32
156 if (!(left is IntConstant))
157 left = left.ToInt (loc);
158 if (!(right is IntConstant))
159 right = right.ToInt (loc);
164 static void Error_CompileTimeOverflow (Location loc)
166 Report.Error (220, loc, "The operation overflows at compile time in checked mode");
170 /// Constant expression folder for binary operations.
172 /// Returns null if the expression can not be folded.
174 static public Expression BinaryFold (EmitContext ec, Binary.Operator oper,
175 Constant left, Constant right, Location loc)
177 if (left is NullCast)
178 return BinaryFold (ec, oper, ((NullCast)left).child, right, loc);
180 if (right is NullCast)
181 return BinaryFold (ec, oper, left, ((NullCast)right).child, loc);
184 Type rt = right.Type;
185 Type result_type = null;
189 // Enumerator folding
191 if (rt == lt && left is EnumConstant)
195 // During an enum evaluation, we need to unwrap enumerations
197 if (ec.InEnumContext){
198 if (left is EnumConstant)
199 left = ((EnumConstant) left).Child;
201 if (right is EnumConstant)
202 right = ((EnumConstant) right).Child;
205 if (left is BoolConstant && right is BoolConstant) {
206 bool lv = ((BoolConstant) left ).Value;
207 bool rv = ((BoolConstant) right).Value;
209 case Binary.Operator.BitwiseAnd:
210 case Binary.Operator.LogicalAnd:
211 return new BoolConstant (lv && rv, left.Location);
212 case Binary.Operator.BitwiseOr:
213 case Binary.Operator.LogicalOr:
214 return new BoolConstant (lv || rv, left.Location);
215 case Binary.Operator.ExclusiveOr:
216 return new BoolConstant (lv ^ rv, left.Location);
218 throw new InternalErrorException ("Invalid operator on booleans: " + oper);
223 Constant result = null;
225 case Binary.Operator.BitwiseOr:
226 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
227 if (left == null || right == null)
230 if (left is IntConstant){
232 int res = ((IntConstant) left).Value | ((IntConstant) right).Value;
234 v = new IntConstant (res, left.Location);
235 if (result_type == null)
238 return new EnumConstant (v, result_type);
239 } else if (left is UIntConstant){
241 uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value;
243 v = new UIntConstant (res, left.Location);
244 if (result_type == null)
247 return new EnumConstant (v, result_type);
248 } else if (left is LongConstant){
250 long res = ((LongConstant)left).Value | ((LongConstant)right).Value;
252 v = new LongConstant (res, left.Location);
253 if (result_type == null)
256 return new EnumConstant (v, result_type);
257 } else if (left is ULongConstant){
259 ulong res = ((ULongConstant)left).Value |
260 ((ULongConstant)right).Value;
262 v = new ULongConstant (res, left.Location);
263 if (result_type == null)
266 return new EnumConstant (v, result_type);
267 } else if (left is UShortConstant){
269 ushort res = (ushort) (((UShortConstant)left).Value |
270 ((UShortConstant)right).Value);
272 v = new UShortConstant (res, left.Location);
273 if (result_type == null)
276 return new EnumConstant (v, result_type);
277 } else if (left is ShortConstant){
279 short res = (short) (((ShortConstant)left).Value |
280 ((ShortConstant)right).Value);
282 v = new ShortConstant (res, left.Location);
283 if (result_type == null)
286 return new EnumConstant (v, result_type);
290 case Binary.Operator.BitwiseAnd:
291 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
292 if (left == null || right == null)
295 if (left is IntConstant){
297 int res = ((IntConstant) left).Value & ((IntConstant) right).Value;
299 v = new IntConstant (res, left.Location);
300 if (result_type == null)
303 return new EnumConstant (v, result_type);
304 } else if (left is UIntConstant){
306 uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value;
308 v = new UIntConstant (res, left.Location);
309 if (result_type == null)
312 return new EnumConstant (v, result_type);
313 } else if (left is LongConstant){
315 long res = ((LongConstant)left).Value & ((LongConstant)right).Value;
317 v = new LongConstant (res, left.Location);
318 if (result_type == null)
321 return new EnumConstant (v, result_type);
322 } else if (left is ULongConstant){
324 ulong res = ((ULongConstant)left).Value &
325 ((ULongConstant)right).Value;
327 v = new ULongConstant (res, left.Location);
328 if (result_type == null)
331 return new EnumConstant (v, result_type);
332 } else if (left is UShortConstant){
334 ushort res = (ushort) (((UShortConstant)left).Value &
335 ((UShortConstant)right).Value);
337 v = new UShortConstant (res, left.Location);
338 if (result_type == null)
341 return new EnumConstant (v, result_type);
342 } else if (left is ShortConstant){
344 short res = (short) (((ShortConstant)left).Value &
345 ((ShortConstant)right).Value);
347 v = new ShortConstant (res, left.Location);
348 if (result_type == null)
351 return new EnumConstant (v, result_type);
355 case Binary.Operator.ExclusiveOr:
356 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
357 if (left == null || right == null)
360 if (left is IntConstant){
362 int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value;
364 v = new IntConstant (res, left.Location);
365 if (result_type == null)
368 return new EnumConstant (v, result_type);
369 } else if (left is UIntConstant){
371 uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value;
373 v = new UIntConstant (res, left.Location);
374 if (result_type == null)
377 return new EnumConstant (v, result_type);
378 } else if (left is LongConstant){
380 long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value;
382 v = new LongConstant (res, left.Location);
383 if (result_type == null)
386 return new EnumConstant (v, result_type);
387 } else if (left is ULongConstant){
389 ulong res = ((ULongConstant)left).Value ^
390 ((ULongConstant)right).Value;
392 v = new ULongConstant (res, left.Location);
393 if (result_type == null)
396 return new EnumConstant (v, result_type);
397 } else if (left is UShortConstant){
399 ushort res = (ushort) (((UShortConstant)left).Value ^
400 ((UShortConstant)right).Value);
402 v = new UShortConstant (res, left.Location);
403 if (result_type == null)
406 return new EnumConstant (v, result_type);
407 } else if (left is ShortConstant){
409 short res = (short)(((ShortConstant)left).Value ^
410 ((ShortConstant)right).Value);
412 v = new ShortConstant (res, left.Location);
413 if (result_type == null)
416 return new EnumConstant (v, result_type);
420 case Binary.Operator.Addition:
421 bool left_is_string = left is StringConstant;
422 bool right_is_string = right is StringConstant;
425 // If both sides are strings, then concatenate, if
426 // one is a string, and the other is not, then defer
427 // to runtime concatenation
430 if (left_is_string || right_is_string){
431 if (left_is_string && right_is_string)
432 return new StringConstant (
433 ((StringConstant) left).Value +
434 ((StringConstant) right).Value, left.Location);
440 // handle "E operator + (E x, U y)"
441 // handle "E operator + (Y y, E x)"
443 // note that E operator + (E x, E y) is invalid
445 if (left is EnumConstant){
446 if (right is EnumConstant){
450 right = right.ToType (((EnumConstant) left).Child.Type, loc);
455 } else if (right is EnumConstant){
456 left = left.ToType (((EnumConstant) right).Child.Type, loc);
460 wrap_as = right.Type;
464 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
465 if (left == null || right == null)
469 if (left is DoubleConstant){
472 if (ec.ConstantCheckState)
473 res = checked (((DoubleConstant) left).Value +
474 ((DoubleConstant) right).Value);
476 res = unchecked (((DoubleConstant) left).Value +
477 ((DoubleConstant) right).Value);
479 result = new DoubleConstant (res, left.Location);
480 } else if (left is FloatConstant){
483 if (ec.ConstantCheckState)
484 res = checked (((FloatConstant) left).Value +
485 ((FloatConstant) right).Value);
487 res = unchecked (((FloatConstant) left).Value +
488 ((FloatConstant) right).Value);
490 result = new FloatConstant (res, left.Location);
491 } else if (left is ULongConstant){
494 if (ec.ConstantCheckState)
495 res = checked (((ULongConstant) left).Value +
496 ((ULongConstant) right).Value);
498 res = unchecked (((ULongConstant) left).Value +
499 ((ULongConstant) right).Value);
501 result = new ULongConstant (res, left.Location);
502 } else if (left is LongConstant){
505 if (ec.ConstantCheckState)
506 res = checked (((LongConstant) left).Value +
507 ((LongConstant) right).Value);
509 res = unchecked (((LongConstant) left).Value +
510 ((LongConstant) right).Value);
512 result = new LongConstant (res, left.Location);
513 } else if (left is UIntConstant){
516 if (ec.ConstantCheckState)
517 res = checked (((UIntConstant) left).Value +
518 ((UIntConstant) right).Value);
520 res = unchecked (((UIntConstant) left).Value +
521 ((UIntConstant) right).Value);
523 result = new UIntConstant (res, left.Location);
524 } else if (left is IntConstant){
527 if (ec.ConstantCheckState)
528 res = checked (((IntConstant) left).Value +
529 ((IntConstant) right).Value);
531 res = unchecked (((IntConstant) left).Value +
532 ((IntConstant) right).Value);
534 result = new IntConstant (res, left.Location);
535 } else if (left is DecimalConstant) {
538 if (ec.ConstantCheckState)
539 res = checked (((DecimalConstant) left).Value +
540 ((DecimalConstant) right).Value);
542 res = unchecked (((DecimalConstant) left).Value +
543 ((DecimalConstant) right).Value);
545 result = new DecimalConstant (res, left.Location);
547 throw new Exception ( "Unexepected addition input: " + left);
549 } catch (OverflowException){
550 Error_CompileTimeOverflow (loc);
553 if (wrap_as != null) {
555 return result.TryReduce (ec, wrap_as, loc);
557 catch (OverflowException) {
564 case Binary.Operator.Subtraction:
566 // handle "E operator - (E x, U y)"
567 // handle "E operator - (Y y, E x)"
568 // handle "U operator - (E x, E y)"
571 if (left is EnumConstant){
572 if (right is EnumConstant){
573 if (left.Type != right.Type) {
574 Binary.Error_OperatorCannotBeApplied (loc, "-", left.Type, right.Type);
578 wrap_as = TypeManager.EnumToUnderlying (left.Type);
579 right = ((EnumConstant) right).Child.ToType (wrap_as, loc);
583 left = ((EnumConstant) left).Child.ToType (wrap_as, loc);
588 right = right.ToType (((EnumConstant) left).Child.Type, loc);
594 } else if (right is EnumConstant){
595 left = left.ToType (((EnumConstant) right).Child.Type, loc);
599 wrap_as = right.Type;
602 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
603 if (left == null || right == null)
607 if (left is DoubleConstant){
610 if (ec.ConstantCheckState)
611 res = checked (((DoubleConstant) left).Value -
612 ((DoubleConstant) right).Value);
614 res = unchecked (((DoubleConstant) left).Value -
615 ((DoubleConstant) right).Value);
617 result = new DoubleConstant (res, left.Location);
618 } else if (left is FloatConstant){
621 if (ec.ConstantCheckState)
622 res = checked (((FloatConstant) left).Value -
623 ((FloatConstant) right).Value);
625 res = unchecked (((FloatConstant) left).Value -
626 ((FloatConstant) right).Value);
628 result = new FloatConstant (res, left.Location);
629 } else if (left is ULongConstant){
632 if (ec.ConstantCheckState)
633 res = checked (((ULongConstant) left).Value -
634 ((ULongConstant) right).Value);
636 res = unchecked (((ULongConstant) left).Value -
637 ((ULongConstant) right).Value);
639 result = new ULongConstant (res, left.Location);
640 } else if (left is LongConstant){
643 if (ec.ConstantCheckState)
644 res = checked (((LongConstant) left).Value -
645 ((LongConstant) right).Value);
647 res = unchecked (((LongConstant) left).Value -
648 ((LongConstant) right).Value);
650 result = new LongConstant (res, left.Location);
651 } else if (left is UIntConstant){
654 if (ec.ConstantCheckState)
655 res = checked (((UIntConstant) left).Value -
656 ((UIntConstant) right).Value);
658 res = unchecked (((UIntConstant) left).Value -
659 ((UIntConstant) right).Value);
661 result = new UIntConstant (res, left.Location);
662 } else if (left is IntConstant){
665 if (ec.ConstantCheckState)
666 res = checked (((IntConstant) left).Value -
667 ((IntConstant) right).Value);
669 res = unchecked (((IntConstant) left).Value -
670 ((IntConstant) right).Value);
672 result = new IntConstant (res, left.Location);
673 } else if (left is DecimalConstant) {
676 if (ec.ConstantCheckState)
677 res = checked (((DecimalConstant) left).Value -
678 ((DecimalConstant) right).Value);
680 res = unchecked (((DecimalConstant) left).Value -
681 ((DecimalConstant) right).Value);
683 return new DecimalConstant (res, left.Location);
685 throw new Exception ( "Unexepected subtraction input: " + left);
687 } catch (OverflowException){
688 Error_CompileTimeOverflow (loc);
691 if (wrap_as != null) {
693 return result.TryReduce (ec, wrap_as, loc);
695 catch (OverflowException) {
702 case Binary.Operator.Multiply:
703 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
704 if (left == null || right == null)
708 if (left is DoubleConstant){
711 if (ec.ConstantCheckState)
712 res = checked (((DoubleConstant) left).Value *
713 ((DoubleConstant) right).Value);
715 res = unchecked (((DoubleConstant) left).Value *
716 ((DoubleConstant) right).Value);
718 return new DoubleConstant (res, left.Location);
719 } else if (left is FloatConstant){
722 if (ec.ConstantCheckState)
723 res = checked (((FloatConstant) left).Value *
724 ((FloatConstant) right).Value);
726 res = unchecked (((FloatConstant) left).Value *
727 ((FloatConstant) right).Value);
729 return new FloatConstant (res, left.Location);
730 } else if (left is ULongConstant){
733 if (ec.ConstantCheckState)
734 res = checked (((ULongConstant) left).Value *
735 ((ULongConstant) right).Value);
737 res = unchecked (((ULongConstant) left).Value *
738 ((ULongConstant) right).Value);
740 return new ULongConstant (res, left.Location);
741 } else if (left is LongConstant){
744 if (ec.ConstantCheckState)
745 res = checked (((LongConstant) left).Value *
746 ((LongConstant) right).Value);
748 res = unchecked (((LongConstant) left).Value *
749 ((LongConstant) right).Value);
751 return new LongConstant (res, left.Location);
752 } else if (left is UIntConstant){
755 if (ec.ConstantCheckState)
756 res = checked (((UIntConstant) left).Value *
757 ((UIntConstant) right).Value);
759 res = unchecked (((UIntConstant) left).Value *
760 ((UIntConstant) right).Value);
762 return new UIntConstant (res, left.Location);
763 } else if (left is IntConstant){
766 if (ec.ConstantCheckState)
767 res = checked (((IntConstant) left).Value *
768 ((IntConstant) right).Value);
770 res = unchecked (((IntConstant) left).Value *
771 ((IntConstant) right).Value);
773 return new IntConstant (res, left.Location);
774 } else if (left is DecimalConstant) {
777 if (ec.ConstantCheckState)
778 res = checked (((DecimalConstant) left).Value *
779 ((DecimalConstant) right).Value);
781 res = unchecked (((DecimalConstant) left).Value *
782 ((DecimalConstant) right).Value);
784 return new DecimalConstant (res, left.Location);
786 throw new Exception ( "Unexepected multiply input: " + left);
788 } catch (OverflowException){
789 Error_CompileTimeOverflow (loc);
793 case Binary.Operator.Division:
794 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
795 if (left == null || right == null)
799 if (left is DoubleConstant){
802 if (ec.ConstantCheckState)
803 res = checked (((DoubleConstant) left).Value /
804 ((DoubleConstant) right).Value);
806 res = unchecked (((DoubleConstant) left).Value /
807 ((DoubleConstant) right).Value);
809 return new DoubleConstant (res, left.Location);
810 } else if (left is FloatConstant){
813 if (ec.ConstantCheckState)
814 res = checked (((FloatConstant) left).Value /
815 ((FloatConstant) right).Value);
817 res = unchecked (((FloatConstant) left).Value /
818 ((FloatConstant) right).Value);
820 return new FloatConstant (res, left.Location);
821 } else if (left is ULongConstant){
824 if (ec.ConstantCheckState)
825 res = checked (((ULongConstant) left).Value /
826 ((ULongConstant) right).Value);
828 res = unchecked (((ULongConstant) left).Value /
829 ((ULongConstant) right).Value);
831 return new ULongConstant (res, left.Location);
832 } else if (left is LongConstant){
835 if (ec.ConstantCheckState)
836 res = checked (((LongConstant) left).Value /
837 ((LongConstant) right).Value);
839 res = unchecked (((LongConstant) left).Value /
840 ((LongConstant) right).Value);
842 return new LongConstant (res, left.Location);
843 } else if (left is UIntConstant){
846 if (ec.ConstantCheckState)
847 res = checked (((UIntConstant) left).Value /
848 ((UIntConstant) right).Value);
850 res = unchecked (((UIntConstant) left).Value /
851 ((UIntConstant) right).Value);
853 return new UIntConstant (res, left.Location);
854 } else if (left is IntConstant){
857 if (ec.ConstantCheckState)
858 res = checked (((IntConstant) left).Value /
859 ((IntConstant) right).Value);
861 res = unchecked (((IntConstant) left).Value /
862 ((IntConstant) right).Value);
864 return new IntConstant (res, left.Location);
865 } else if (left is DecimalConstant) {
868 if (ec.ConstantCheckState)
869 res = checked (((DecimalConstant) left).Value /
870 ((DecimalConstant) right).Value);
872 res = unchecked (((DecimalConstant) left).Value /
873 ((DecimalConstant) right).Value);
875 return new DecimalConstant (res, left.Location);
877 throw new Exception ( "Unexepected division input: " + left);
879 } catch (OverflowException){
880 Error_CompileTimeOverflow (loc);
882 } catch (DivideByZeroException) {
883 Report.Error (020, loc, "Division by constant zero");
888 case Binary.Operator.Modulus:
889 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
890 if (left == null || right == null)
894 if (left is DoubleConstant){
897 if (ec.ConstantCheckState)
898 res = checked (((DoubleConstant) left).Value %
899 ((DoubleConstant) right).Value);
901 res = unchecked (((DoubleConstant) left).Value %
902 ((DoubleConstant) right).Value);
904 return new DoubleConstant (res, left.Location);
905 } else if (left is FloatConstant){
908 if (ec.ConstantCheckState)
909 res = checked (((FloatConstant) left).Value %
910 ((FloatConstant) right).Value);
912 res = unchecked (((FloatConstant) left).Value %
913 ((FloatConstant) right).Value);
915 return new FloatConstant (res, left.Location);
916 } else if (left is ULongConstant){
919 if (ec.ConstantCheckState)
920 res = checked (((ULongConstant) left).Value %
921 ((ULongConstant) right).Value);
923 res = unchecked (((ULongConstant) left).Value %
924 ((ULongConstant) right).Value);
926 return new ULongConstant (res, left.Location);
927 } else if (left is LongConstant){
930 if (ec.ConstantCheckState)
931 res = checked (((LongConstant) left).Value %
932 ((LongConstant) right).Value);
934 res = unchecked (((LongConstant) left).Value %
935 ((LongConstant) right).Value);
937 return new LongConstant (res, left.Location);
938 } else if (left is UIntConstant){
941 if (ec.ConstantCheckState)
942 res = checked (((UIntConstant) left).Value %
943 ((UIntConstant) right).Value);
945 res = unchecked (((UIntConstant) left).Value %
946 ((UIntConstant) right).Value);
948 return new UIntConstant (res, left.Location);
949 } else if (left is IntConstant){
952 if (ec.ConstantCheckState)
953 res = checked (((IntConstant) left).Value %
954 ((IntConstant) right).Value);
956 res = unchecked (((IntConstant) left).Value %
957 ((IntConstant) right).Value);
959 return new IntConstant (res, left.Location);
961 throw new Exception ( "Unexepected modulus input: " + left);
963 } catch (DivideByZeroException){
964 Report.Error (020, loc, "Division by constant zero");
965 } catch (OverflowException){
966 Error_CompileTimeOverflow (loc);
971 // There is no overflow checking on left shift
973 case Binary.Operator.LeftShift:
974 IntConstant ic = right.ToInt (loc);
976 Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
979 int lshift_val = ic.Value;
982 if ((lic = left.ConvertToInt ()) != null)
983 return new IntConstant (lic.Value << lshift_val, left.Location);
986 if ((luic = left.ConvertToUInt ()) != null)
987 return new UIntConstant (luic.Value << lshift_val, left.Location);
990 if ((llc = left.ConvertToLong ()) != null)
991 return new LongConstant (llc.Value << lshift_val, left.Location);
994 if ((lulc = left.ConvertToULong ()) != null)
995 return new ULongConstant (lulc.Value << lshift_val, left.Location);
997 Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
1001 // There is no overflow checking on right shift
1003 case Binary.Operator.RightShift:
1004 IntConstant sic = right.ToInt (loc);
1006 Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
1009 int rshift_val = sic.Value;
1012 if ((ric = left.ConvertToInt ()) != null)
1013 return new IntConstant (ric.Value >> rshift_val, left.Location);
1016 if ((ruic = left.ConvertToUInt ()) != null)
1017 return new UIntConstant (ruic.Value >> rshift_val, left.Location);
1020 if ((rlc = left.ConvertToLong ()) != null)
1021 return new LongConstant (rlc.Value >> rshift_val, left.Location);
1024 if ((rulc = left.ConvertToULong ()) != null)
1025 return new ULongConstant (rulc.Value >> rshift_val, left.Location);
1027 Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
1030 case Binary.Operator.Equality:
1031 if (left is BoolConstant && right is BoolConstant){
1032 return new BoolConstant (
1033 ((BoolConstant) left).Value ==
1034 ((BoolConstant) right).Value, left.Location);
1037 if (left is NullLiteral){
1038 if (right is NullLiteral)
1039 return new BoolConstant (true, left.Location);
1040 else if (right is StringConstant)
1041 return new BoolConstant (
1042 ((StringConstant) right).Value == null, left.Location);
1043 } else if (right is NullLiteral){
1044 if (left is NullLiteral)
1045 return new BoolConstant (true, left.Location);
1046 else if (left is StringConstant)
1047 return new BoolConstant (
1048 ((StringConstant) left).Value == null, left.Location);
1050 if (left is StringConstant && right is StringConstant){
1051 return new BoolConstant (
1052 ((StringConstant) left).Value ==
1053 ((StringConstant) right).Value, left.Location);
1057 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1058 if (left == null || right == null)
1062 if (left is DoubleConstant)
1063 bool_res = ((DoubleConstant) left).Value ==
1064 ((DoubleConstant) right).Value;
1065 else if (left is FloatConstant)
1066 bool_res = ((FloatConstant) left).Value ==
1067 ((FloatConstant) right).Value;
1068 else if (left is ULongConstant)
1069 bool_res = ((ULongConstant) left).Value ==
1070 ((ULongConstant) right).Value;
1071 else if (left is LongConstant)
1072 bool_res = ((LongConstant) left).Value ==
1073 ((LongConstant) right).Value;
1074 else if (left is UIntConstant)
1075 bool_res = ((UIntConstant) left).Value ==
1076 ((UIntConstant) right).Value;
1077 else if (left is IntConstant)
1078 bool_res = ((IntConstant) left).Value ==
1079 ((IntConstant) right).Value;
1083 return new BoolConstant (bool_res, left.Location);
1085 case Binary.Operator.Inequality:
1086 if (left is BoolConstant && right is BoolConstant){
1087 return new BoolConstant (
1088 ((BoolConstant) left).Value !=
1089 ((BoolConstant) right).Value, left.Location);
1091 if (left is NullLiteral){
1092 if (right is NullLiteral)
1093 return new BoolConstant (false, left.Location);
1094 else if (right is StringConstant)
1095 return new BoolConstant (
1096 ((StringConstant) right).Value != null, left.Location);
1097 } else if (right is NullLiteral){
1098 if (left is NullLiteral)
1099 return new BoolConstant (false, left.Location);
1100 else if (left is StringConstant)
1101 return new BoolConstant (
1102 ((StringConstant) left).Value != null, left.Location);
1104 if (left is StringConstant && right is StringConstant){
1105 return new BoolConstant (
1106 ((StringConstant) left).Value !=
1107 ((StringConstant) right).Value, left.Location);
1110 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1111 if (left == null || right == null)
1115 if (left is DoubleConstant)
1116 bool_res = ((DoubleConstant) left).Value !=
1117 ((DoubleConstant) right).Value;
1118 else if (left is FloatConstant)
1119 bool_res = ((FloatConstant) left).Value !=
1120 ((FloatConstant) right).Value;
1121 else if (left is ULongConstant)
1122 bool_res = ((ULongConstant) left).Value !=
1123 ((ULongConstant) right).Value;
1124 else if (left is LongConstant)
1125 bool_res = ((LongConstant) left).Value !=
1126 ((LongConstant) right).Value;
1127 else if (left is UIntConstant)
1128 bool_res = ((UIntConstant) left).Value !=
1129 ((UIntConstant) right).Value;
1130 else if (left is IntConstant)
1131 bool_res = ((IntConstant) left).Value !=
1132 ((IntConstant) right).Value;
1136 return new BoolConstant (bool_res, left.Location);
1138 case Binary.Operator.LessThan:
1139 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1140 if (left == null || right == null)
1144 if (left is DoubleConstant)
1145 bool_res = ((DoubleConstant) left).Value <
1146 ((DoubleConstant) right).Value;
1147 else if (left is FloatConstant)
1148 bool_res = ((FloatConstant) left).Value <
1149 ((FloatConstant) right).Value;
1150 else if (left is ULongConstant)
1151 bool_res = ((ULongConstant) left).Value <
1152 ((ULongConstant) right).Value;
1153 else if (left is LongConstant)
1154 bool_res = ((LongConstant) left).Value <
1155 ((LongConstant) right).Value;
1156 else if (left is UIntConstant)
1157 bool_res = ((UIntConstant) left).Value <
1158 ((UIntConstant) right).Value;
1159 else if (left is IntConstant)
1160 bool_res = ((IntConstant) left).Value <
1161 ((IntConstant) right).Value;
1165 return new BoolConstant (bool_res, left.Location);
1167 case Binary.Operator.GreaterThan:
1168 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1169 if (left == null || right == null)
1173 if (left is DoubleConstant)
1174 bool_res = ((DoubleConstant) left).Value >
1175 ((DoubleConstant) right).Value;
1176 else if (left is FloatConstant)
1177 bool_res = ((FloatConstant) left).Value >
1178 ((FloatConstant) right).Value;
1179 else if (left is ULongConstant)
1180 bool_res = ((ULongConstant) left).Value >
1181 ((ULongConstant) right).Value;
1182 else if (left is LongConstant)
1183 bool_res = ((LongConstant) left).Value >
1184 ((LongConstant) right).Value;
1185 else if (left is UIntConstant)
1186 bool_res = ((UIntConstant) left).Value >
1187 ((UIntConstant) right).Value;
1188 else if (left is IntConstant)
1189 bool_res = ((IntConstant) left).Value >
1190 ((IntConstant) right).Value;
1194 return new BoolConstant (bool_res, left.Location);
1196 case Binary.Operator.GreaterThanOrEqual:
1197 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1198 if (left == null || right == null)
1202 if (left is DoubleConstant)
1203 bool_res = ((DoubleConstant) left).Value >=
1204 ((DoubleConstant) right).Value;
1205 else if (left is FloatConstant)
1206 bool_res = ((FloatConstant) left).Value >=
1207 ((FloatConstant) right).Value;
1208 else if (left is ULongConstant)
1209 bool_res = ((ULongConstant) left).Value >=
1210 ((ULongConstant) right).Value;
1211 else if (left is LongConstant)
1212 bool_res = ((LongConstant) left).Value >=
1213 ((LongConstant) right).Value;
1214 else if (left is UIntConstant)
1215 bool_res = ((UIntConstant) left).Value >=
1216 ((UIntConstant) right).Value;
1217 else if (left is IntConstant)
1218 bool_res = ((IntConstant) left).Value >=
1219 ((IntConstant) right).Value;
1223 return new BoolConstant (bool_res, left.Location);
1225 case Binary.Operator.LessThanOrEqual:
1226 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1227 if (left == null || right == null)
1231 if (left is DoubleConstant)
1232 bool_res = ((DoubleConstant) left).Value <=
1233 ((DoubleConstant) right).Value;
1234 else if (left is FloatConstant)
1235 bool_res = ((FloatConstant) left).Value <=
1236 ((FloatConstant) right).Value;
1237 else if (left is ULongConstant)
1238 bool_res = ((ULongConstant) left).Value <=
1239 ((ULongConstant) right).Value;
1240 else if (left is LongConstant)
1241 bool_res = ((LongConstant) left).Value <=
1242 ((LongConstant) right).Value;
1243 else if (left is UIntConstant)
1244 bool_res = ((UIntConstant) left).Value <=
1245 ((UIntConstant) right).Value;
1246 else if (left is IntConstant)
1247 bool_res = ((IntConstant) left).Value <=
1248 ((IntConstant) right).Value;
1252 return new BoolConstant (bool_res, left.Location);