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);
554 return result.TryReduce (ec, wrap_as, loc);
558 case Binary.Operator.Subtraction:
560 // handle "E operator - (E x, U y)"
561 // handle "E operator - (Y y, E x)"
562 // handle "U operator - (E x, E y)"
565 if (left is EnumConstant){
566 if (right is EnumConstant){
567 if (left.Type != right.Type) {
568 Binary.Error_OperatorCannotBeApplied (loc, "-", left.Type, right.Type);
572 wrap_as = TypeManager.EnumToUnderlying (left.Type);
573 right = ((EnumConstant) right).Child.ToType (wrap_as, loc);
577 left = ((EnumConstant) left).Child.ToType (wrap_as, loc);
582 right = right.ToType (((EnumConstant) left).Child.Type, loc);
588 } else if (right is EnumConstant){
589 left = left.ToType (((EnumConstant) right).Child.Type, loc);
593 wrap_as = right.Type;
596 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
597 if (left == null || right == null)
601 if (left is DoubleConstant){
604 if (ec.ConstantCheckState)
605 res = checked (((DoubleConstant) left).Value -
606 ((DoubleConstant) right).Value);
608 res = unchecked (((DoubleConstant) left).Value -
609 ((DoubleConstant) right).Value);
611 result = new DoubleConstant (res, left.Location);
612 } else if (left is FloatConstant){
615 if (ec.ConstantCheckState)
616 res = checked (((FloatConstant) left).Value -
617 ((FloatConstant) right).Value);
619 res = unchecked (((FloatConstant) left).Value -
620 ((FloatConstant) right).Value);
622 result = new FloatConstant (res, left.Location);
623 } else if (left is ULongConstant){
626 if (ec.ConstantCheckState)
627 res = checked (((ULongConstant) left).Value -
628 ((ULongConstant) right).Value);
630 res = unchecked (((ULongConstant) left).Value -
631 ((ULongConstant) right).Value);
633 result = new ULongConstant (res, left.Location);
634 } else if (left is LongConstant){
637 if (ec.ConstantCheckState)
638 res = checked (((LongConstant) left).Value -
639 ((LongConstant) right).Value);
641 res = unchecked (((LongConstant) left).Value -
642 ((LongConstant) right).Value);
644 result = new LongConstant (res, left.Location);
645 } else if (left is UIntConstant){
648 if (ec.ConstantCheckState)
649 res = checked (((UIntConstant) left).Value -
650 ((UIntConstant) right).Value);
652 res = unchecked (((UIntConstant) left).Value -
653 ((UIntConstant) right).Value);
655 result = new UIntConstant (res, left.Location);
656 } else if (left is IntConstant){
659 if (ec.ConstantCheckState)
660 res = checked (((IntConstant) left).Value -
661 ((IntConstant) right).Value);
663 res = unchecked (((IntConstant) left).Value -
664 ((IntConstant) right).Value);
666 result = new IntConstant (res, left.Location);
667 } else if (left is DecimalConstant) {
670 if (ec.ConstantCheckState)
671 res = checked (((DecimalConstant) left).Value -
672 ((DecimalConstant) right).Value);
674 res = unchecked (((DecimalConstant) left).Value -
675 ((DecimalConstant) right).Value);
677 return new DecimalConstant (res, left.Location);
679 throw new Exception ( "Unexepected subtraction input: " + left);
681 } catch (OverflowException){
682 Error_CompileTimeOverflow (loc);
686 return result.TryReduce (ec, wrap_as, loc);
690 case Binary.Operator.Multiply:
691 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
692 if (left == null || right == null)
696 if (left is DoubleConstant){
699 if (ec.ConstantCheckState)
700 res = checked (((DoubleConstant) left).Value *
701 ((DoubleConstant) right).Value);
703 res = unchecked (((DoubleConstant) left).Value *
704 ((DoubleConstant) right).Value);
706 return new DoubleConstant (res, left.Location);
707 } else if (left is FloatConstant){
710 if (ec.ConstantCheckState)
711 res = checked (((FloatConstant) left).Value *
712 ((FloatConstant) right).Value);
714 res = unchecked (((FloatConstant) left).Value *
715 ((FloatConstant) right).Value);
717 return new FloatConstant (res, left.Location);
718 } else if (left is ULongConstant){
721 if (ec.ConstantCheckState)
722 res = checked (((ULongConstant) left).Value *
723 ((ULongConstant) right).Value);
725 res = unchecked (((ULongConstant) left).Value *
726 ((ULongConstant) right).Value);
728 return new ULongConstant (res, left.Location);
729 } else if (left is LongConstant){
732 if (ec.ConstantCheckState)
733 res = checked (((LongConstant) left).Value *
734 ((LongConstant) right).Value);
736 res = unchecked (((LongConstant) left).Value *
737 ((LongConstant) right).Value);
739 return new LongConstant (res, left.Location);
740 } else if (left is UIntConstant){
743 if (ec.ConstantCheckState)
744 res = checked (((UIntConstant) left).Value *
745 ((UIntConstant) right).Value);
747 res = unchecked (((UIntConstant) left).Value *
748 ((UIntConstant) right).Value);
750 return new UIntConstant (res, left.Location);
751 } else if (left is IntConstant){
754 if (ec.ConstantCheckState)
755 res = checked (((IntConstant) left).Value *
756 ((IntConstant) right).Value);
758 res = unchecked (((IntConstant) left).Value *
759 ((IntConstant) right).Value);
761 return new IntConstant (res, left.Location);
762 } else if (left is DecimalConstant) {
765 if (ec.ConstantCheckState)
766 res = checked (((DecimalConstant) left).Value *
767 ((DecimalConstant) right).Value);
769 res = unchecked (((DecimalConstant) left).Value *
770 ((DecimalConstant) right).Value);
772 return new DecimalConstant (res, left.Location);
774 throw new Exception ( "Unexepected multiply input: " + left);
776 } catch (OverflowException){
777 Error_CompileTimeOverflow (loc);
781 case Binary.Operator.Division:
782 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
783 if (left == null || right == null)
787 if (left is DoubleConstant){
790 if (ec.ConstantCheckState)
791 res = checked (((DoubleConstant) left).Value /
792 ((DoubleConstant) right).Value);
794 res = unchecked (((DoubleConstant) left).Value /
795 ((DoubleConstant) right).Value);
797 return new DoubleConstant (res, left.Location);
798 } else if (left is FloatConstant){
801 if (ec.ConstantCheckState)
802 res = checked (((FloatConstant) left).Value /
803 ((FloatConstant) right).Value);
805 res = unchecked (((FloatConstant) left).Value /
806 ((FloatConstant) right).Value);
808 return new FloatConstant (res, left.Location);
809 } else if (left is ULongConstant){
812 if (ec.ConstantCheckState)
813 res = checked (((ULongConstant) left).Value /
814 ((ULongConstant) right).Value);
816 res = unchecked (((ULongConstant) left).Value /
817 ((ULongConstant) right).Value);
819 return new ULongConstant (res, left.Location);
820 } else if (left is LongConstant){
823 if (ec.ConstantCheckState)
824 res = checked (((LongConstant) left).Value /
825 ((LongConstant) right).Value);
827 res = unchecked (((LongConstant) left).Value /
828 ((LongConstant) right).Value);
830 return new LongConstant (res, left.Location);
831 } else if (left is UIntConstant){
834 if (ec.ConstantCheckState)
835 res = checked (((UIntConstant) left).Value /
836 ((UIntConstant) right).Value);
838 res = unchecked (((UIntConstant) left).Value /
839 ((UIntConstant) right).Value);
841 return new UIntConstant (res, left.Location);
842 } else if (left is IntConstant){
845 if (ec.ConstantCheckState)
846 res = checked (((IntConstant) left).Value /
847 ((IntConstant) right).Value);
849 res = unchecked (((IntConstant) left).Value /
850 ((IntConstant) right).Value);
852 return new IntConstant (res, left.Location);
853 } else if (left is DecimalConstant) {
856 if (ec.ConstantCheckState)
857 res = checked (((DecimalConstant) left).Value /
858 ((DecimalConstant) right).Value);
860 res = unchecked (((DecimalConstant) left).Value /
861 ((DecimalConstant) right).Value);
863 return new DecimalConstant (res, left.Location);
865 throw new Exception ( "Unexepected division input: " + left);
867 } catch (OverflowException){
868 Error_CompileTimeOverflow (loc);
870 } catch (DivideByZeroException) {
871 Report.Error (020, loc, "Division by constant zero");
876 case Binary.Operator.Modulus:
877 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
878 if (left == null || right == null)
882 if (left is DoubleConstant){
885 if (ec.ConstantCheckState)
886 res = checked (((DoubleConstant) left).Value %
887 ((DoubleConstant) right).Value);
889 res = unchecked (((DoubleConstant) left).Value %
890 ((DoubleConstant) right).Value);
892 return new DoubleConstant (res, left.Location);
893 } else if (left is FloatConstant){
896 if (ec.ConstantCheckState)
897 res = checked (((FloatConstant) left).Value %
898 ((FloatConstant) right).Value);
900 res = unchecked (((FloatConstant) left).Value %
901 ((FloatConstant) right).Value);
903 return new FloatConstant (res, left.Location);
904 } else if (left is ULongConstant){
907 if (ec.ConstantCheckState)
908 res = checked (((ULongConstant) left).Value %
909 ((ULongConstant) right).Value);
911 res = unchecked (((ULongConstant) left).Value %
912 ((ULongConstant) right).Value);
914 return new ULongConstant (res, left.Location);
915 } else if (left is LongConstant){
918 if (ec.ConstantCheckState)
919 res = checked (((LongConstant) left).Value %
920 ((LongConstant) right).Value);
922 res = unchecked (((LongConstant) left).Value %
923 ((LongConstant) right).Value);
925 return new LongConstant (res, left.Location);
926 } else if (left is UIntConstant){
929 if (ec.ConstantCheckState)
930 res = checked (((UIntConstant) left).Value %
931 ((UIntConstant) right).Value);
933 res = unchecked (((UIntConstant) left).Value %
934 ((UIntConstant) right).Value);
936 return new UIntConstant (res, left.Location);
937 } else if (left is IntConstant){
940 if (ec.ConstantCheckState)
941 res = checked (((IntConstant) left).Value %
942 ((IntConstant) right).Value);
944 res = unchecked (((IntConstant) left).Value %
945 ((IntConstant) right).Value);
947 return new IntConstant (res, left.Location);
949 throw new Exception ( "Unexepected modulus input: " + left);
951 } catch (DivideByZeroException){
952 Report.Error (020, loc, "Division by constant zero");
953 } catch (OverflowException){
954 Error_CompileTimeOverflow (loc);
959 // There is no overflow checking on left shift
961 case Binary.Operator.LeftShift:
962 IntConstant ic = right.ToInt (loc);
964 Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
967 int lshift_val = ic.Value;
970 if ((lic = left.ConvertToInt ()) != null)
971 return new IntConstant (lic.Value << lshift_val, left.Location);
974 if ((luic = left.ConvertToUInt ()) != null)
975 return new UIntConstant (luic.Value << lshift_val, left.Location);
978 if ((llc = left.ConvertToLong ()) != null)
979 return new LongConstant (llc.Value << lshift_val, left.Location);
982 if ((lulc = left.ConvertToULong ()) != null)
983 return new ULongConstant (lulc.Value << lshift_val, left.Location);
985 Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
989 // There is no overflow checking on right shift
991 case Binary.Operator.RightShift:
992 IntConstant sic = right.ToInt (loc);
994 Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
997 int rshift_val = sic.Value;
1000 if ((ric = left.ConvertToInt ()) != null)
1001 return new IntConstant (ric.Value >> rshift_val, left.Location);
1004 if ((ruic = left.ConvertToUInt ()) != null)
1005 return new UIntConstant (ruic.Value >> rshift_val, left.Location);
1008 if ((rlc = left.ConvertToLong ()) != null)
1009 return new LongConstant (rlc.Value >> rshift_val, left.Location);
1012 if ((rulc = left.ConvertToULong ()) != null)
1013 return new ULongConstant (rulc.Value >> rshift_val, left.Location);
1015 Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
1018 case Binary.Operator.Equality:
1019 if (left is BoolConstant && right is BoolConstant){
1020 return new BoolConstant (
1021 ((BoolConstant) left).Value ==
1022 ((BoolConstant) right).Value, left.Location);
1025 if (left is NullLiteral){
1026 if (right is NullLiteral)
1027 return new BoolConstant (true, left.Location);
1028 else if (right is StringConstant)
1029 return new BoolConstant (
1030 ((StringConstant) right).Value == null, left.Location);
1031 } else if (right is NullLiteral){
1032 if (left is NullLiteral)
1033 return new BoolConstant (true, left.Location);
1034 else if (left is StringConstant)
1035 return new BoolConstant (
1036 ((StringConstant) left).Value == null, left.Location);
1038 if (left is StringConstant && right is StringConstant){
1039 return new BoolConstant (
1040 ((StringConstant) left).Value ==
1041 ((StringConstant) right).Value, left.Location);
1045 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1046 if (left == null || right == null)
1050 if (left is DoubleConstant)
1051 bool_res = ((DoubleConstant) left).Value ==
1052 ((DoubleConstant) right).Value;
1053 else if (left is FloatConstant)
1054 bool_res = ((FloatConstant) left).Value ==
1055 ((FloatConstant) right).Value;
1056 else if (left is ULongConstant)
1057 bool_res = ((ULongConstant) left).Value ==
1058 ((ULongConstant) right).Value;
1059 else if (left is LongConstant)
1060 bool_res = ((LongConstant) left).Value ==
1061 ((LongConstant) right).Value;
1062 else if (left is UIntConstant)
1063 bool_res = ((UIntConstant) left).Value ==
1064 ((UIntConstant) right).Value;
1065 else if (left is IntConstant)
1066 bool_res = ((IntConstant) left).Value ==
1067 ((IntConstant) right).Value;
1071 return new BoolConstant (bool_res, left.Location);
1073 case Binary.Operator.Inequality:
1074 if (left is BoolConstant && right is BoolConstant){
1075 return new BoolConstant (
1076 ((BoolConstant) left).Value !=
1077 ((BoolConstant) right).Value, left.Location);
1079 if (left is NullLiteral){
1080 if (right is NullLiteral)
1081 return new BoolConstant (false, left.Location);
1082 else if (right is StringConstant)
1083 return new BoolConstant (
1084 ((StringConstant) right).Value != null, left.Location);
1085 } else if (right is NullLiteral){
1086 if (left is NullLiteral)
1087 return new BoolConstant (false, left.Location);
1088 else if (left is StringConstant)
1089 return new BoolConstant (
1090 ((StringConstant) left).Value != null, left.Location);
1092 if (left is StringConstant && right is StringConstant){
1093 return new BoolConstant (
1094 ((StringConstant) left).Value !=
1095 ((StringConstant) right).Value, left.Location);
1098 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1099 if (left == null || right == null)
1103 if (left is DoubleConstant)
1104 bool_res = ((DoubleConstant) left).Value !=
1105 ((DoubleConstant) right).Value;
1106 else if (left is FloatConstant)
1107 bool_res = ((FloatConstant) left).Value !=
1108 ((FloatConstant) right).Value;
1109 else if (left is ULongConstant)
1110 bool_res = ((ULongConstant) left).Value !=
1111 ((ULongConstant) right).Value;
1112 else if (left is LongConstant)
1113 bool_res = ((LongConstant) left).Value !=
1114 ((LongConstant) right).Value;
1115 else if (left is UIntConstant)
1116 bool_res = ((UIntConstant) left).Value !=
1117 ((UIntConstant) right).Value;
1118 else if (left is IntConstant)
1119 bool_res = ((IntConstant) left).Value !=
1120 ((IntConstant) right).Value;
1124 return new BoolConstant (bool_res, left.Location);
1126 case Binary.Operator.LessThan:
1127 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1128 if (left == null || right == null)
1132 if (left is DoubleConstant)
1133 bool_res = ((DoubleConstant) left).Value <
1134 ((DoubleConstant) right).Value;
1135 else if (left is FloatConstant)
1136 bool_res = ((FloatConstant) left).Value <
1137 ((FloatConstant) right).Value;
1138 else if (left is ULongConstant)
1139 bool_res = ((ULongConstant) left).Value <
1140 ((ULongConstant) right).Value;
1141 else if (left is LongConstant)
1142 bool_res = ((LongConstant) left).Value <
1143 ((LongConstant) right).Value;
1144 else if (left is UIntConstant)
1145 bool_res = ((UIntConstant) left).Value <
1146 ((UIntConstant) right).Value;
1147 else if (left is IntConstant)
1148 bool_res = ((IntConstant) left).Value <
1149 ((IntConstant) right).Value;
1153 return new BoolConstant (bool_res, left.Location);
1155 case Binary.Operator.GreaterThan:
1156 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1157 if (left == null || right == null)
1161 if (left is DoubleConstant)
1162 bool_res = ((DoubleConstant) left).Value >
1163 ((DoubleConstant) right).Value;
1164 else if (left is FloatConstant)
1165 bool_res = ((FloatConstant) left).Value >
1166 ((FloatConstant) right).Value;
1167 else if (left is ULongConstant)
1168 bool_res = ((ULongConstant) left).Value >
1169 ((ULongConstant) right).Value;
1170 else if (left is LongConstant)
1171 bool_res = ((LongConstant) left).Value >
1172 ((LongConstant) right).Value;
1173 else if (left is UIntConstant)
1174 bool_res = ((UIntConstant) left).Value >
1175 ((UIntConstant) right).Value;
1176 else if (left is IntConstant)
1177 bool_res = ((IntConstant) left).Value >
1178 ((IntConstant) right).Value;
1182 return new BoolConstant (bool_res, left.Location);
1184 case Binary.Operator.GreaterThanOrEqual:
1185 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1186 if (left == null || right == null)
1190 if (left is DoubleConstant)
1191 bool_res = ((DoubleConstant) left).Value >=
1192 ((DoubleConstant) right).Value;
1193 else if (left is FloatConstant)
1194 bool_res = ((FloatConstant) left).Value >=
1195 ((FloatConstant) right).Value;
1196 else if (left is ULongConstant)
1197 bool_res = ((ULongConstant) left).Value >=
1198 ((ULongConstant) right).Value;
1199 else if (left is LongConstant)
1200 bool_res = ((LongConstant) left).Value >=
1201 ((LongConstant) right).Value;
1202 else if (left is UIntConstant)
1203 bool_res = ((UIntConstant) left).Value >=
1204 ((UIntConstant) right).Value;
1205 else if (left is IntConstant)
1206 bool_res = ((IntConstant) left).Value >=
1207 ((IntConstant) right).Value;
1211 return new BoolConstant (bool_res, left.Location);
1213 case Binary.Operator.LessThanOrEqual:
1214 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1215 if (left == null || right == null)
1219 if (left is DoubleConstant)
1220 bool_res = ((DoubleConstant) left).Value <=
1221 ((DoubleConstant) right).Value;
1222 else if (left is FloatConstant)
1223 bool_res = ((FloatConstant) left).Value <=
1224 ((FloatConstant) right).Value;
1225 else if (left is ULongConstant)
1226 bool_res = ((ULongConstant) left).Value <=
1227 ((ULongConstant) right).Value;
1228 else if (left is LongConstant)
1229 bool_res = ((LongConstant) left).Value <=
1230 ((LongConstant) right).Value;
1231 else if (left is UIntConstant)
1232 bool_res = ((UIntConstant) left).Value <=
1233 ((UIntConstant) right).Value;
1234 else if (left is IntConstant)
1235 bool_res = ((IntConstant) left).Value <=
1236 ((IntConstant) right).Value;
1240 return new BoolConstant (bool_res, left.Location);