2 // cfold.cs: Constant Folding
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
8 // (C) 2002, 2003 Ximian, Inc.
13 namespace Mono.CSharp {
15 public class ConstantFold {
18 // Performs the numeric promotions on the left and right expresions
19 // and desposits the results on `lc' and `rc'.
21 // On success, the types of `lc' and `rc' on output will always match,
22 // and the pair will be one of:
30 // (short, short) (Happens with enumerations with underlying short type)
31 // (ushort, ushort) (Happens with enumerations with underlying short type)
33 static void DoConstantNumericPromotions (EmitContext ec, Binary.Operator oper,
34 ref Constant left, ref Constant right,
37 if (left is DoubleConstant || right is DoubleConstant){
39 // If either side is a double, convert the other to a double
41 if (!(left is DoubleConstant))
42 left = left.ToDouble (loc);
44 if (!(right is DoubleConstant))
45 right = right.ToDouble (loc);
47 } else if (left is FloatConstant || right is FloatConstant) {
49 // If either side is a float, convert the other to a float
51 if (!(left is FloatConstant))
52 left = left.ToFloat (loc);
54 if (!(right is FloatConstant))
55 right = right.ToFloat (loc);
57 } else if (left is ULongConstant || right is ULongConstant){
59 // If either operand is of type ulong, the other operand is
60 // converted to type ulong. or an error ocurrs if the other
61 // operand is of type sbyte, short, int or long
64 Constant match, other;
67 if (left is ULongConstant){
72 if (!(right is ULongConstant))
73 right = right.ToULong (loc);
79 left = left.ToULong (loc);
83 if (other is SByteConstant || other is ShortConstant ||
84 other is IntConstant || other is LongConstant){
85 Binary.Error_OperatorAmbiguous
86 (loc, oper, other.Type, match.Type);
92 } else if (left is LongConstant || right is LongConstant){
94 // If either operand is of type long, the other operand is converted
97 if (!(left is LongConstant))
98 left = left.ToLong (loc);
99 else if (!(right is LongConstant))
100 right = right.ToLong (loc);
102 } else if (left is UIntConstant || right is UIntConstant){
104 // If either operand is of type uint, and the other
105 // operand is of type sbyte, short or int, the operands are
106 // converted to type long.
109 if (left is UIntConstant)
115 if (other is UIntConstant)
118 IntConstant ic = other as IntConstant;
122 left = new UIntConstant ((uint) ic.Value, ic.Location);
124 right = new UIntConstant ((uint) ic.Value, ic.Location);
129 if (other is SByteConstant || other is ShortConstant || ic != null){
130 left = left.ToLong (loc);
131 right = right.ToLong (loc);
133 left = left.ToUInt (loc);
134 right = left.ToUInt (loc);
138 } else if (left is DecimalConstant || right is DecimalConstant) {
139 if (!(left is DecimalConstant))
140 left = left.ToDecimal (loc);
141 else if (!(right is DecimalConstant))
142 right = right.ToDecimal (loc);
144 } else if (left is EnumConstant || right is EnumConstant){
145 if (left is EnumConstant)
146 left = ((EnumConstant) left).Child;
147 if (right is EnumConstant)
148 right = ((EnumConstant) right).Child;
150 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
155 // Force conversions to int32
157 if (!(left is IntConstant))
158 left = left.ToInt (loc);
159 if (!(right is IntConstant))
160 right = right.ToInt (loc);
165 static void Error_CompileTimeOverflow (Location loc)
167 Report.Error (220, loc, "The operation overflows at compile time in checked mode");
171 /// Constant expression folder for binary operations.
173 /// Returns null if the expression can not be folded.
175 static public Expression BinaryFold (EmitContext ec, Binary.Operator oper,
176 Constant left, Constant right, Location loc)
178 if (left is EmptyConstantCast)
179 return BinaryFold (ec, oper, ((EmptyConstantCast)left).child, right, loc);
181 if (right is EmptyConstantCast)
182 return BinaryFold (ec, oper, left, ((EmptyConstantCast)right).child, loc);
185 Type rt = right.Type;
186 Type result_type = null;
190 // Enumerator folding
192 if (rt == lt && left is EnumConstant)
196 // During an enum evaluation, we need to unwrap enumerations
198 if (ec.InEnumContext){
199 if (left is EnumConstant)
200 left = ((EnumConstant) left).Child;
202 if (right is EnumConstant)
203 right = ((EnumConstant) right).Child;
206 if (left is BoolConstant && right is BoolConstant) {
207 bool lv = ((BoolConstant) left ).Value;
208 bool rv = ((BoolConstant) right).Value;
210 case Binary.Operator.BitwiseAnd:
211 case Binary.Operator.LogicalAnd:
212 return new BoolConstant (lv && rv, left.Location);
213 case Binary.Operator.BitwiseOr:
214 case Binary.Operator.LogicalOr:
215 return new BoolConstant (lv || rv, left.Location);
216 case Binary.Operator.ExclusiveOr:
217 return new BoolConstant (lv ^ rv, left.Location);
218 case Binary.Operator.Equality:
219 return new BoolConstant (lv == rv, left.Location);
220 case Binary.Operator.Inequality:
221 return new BoolConstant (lv != rv, left.Location);
223 throw new InternalErrorException ("Invalid operator on booleans: " + oper);
228 Constant result = null;
230 case Binary.Operator.BitwiseOr:
231 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
232 if (left == null || right == null)
235 if (left is IntConstant){
237 int res = ((IntConstant) left).Value | ((IntConstant) right).Value;
239 v = new IntConstant (res, left.Location);
240 if (result_type == null)
243 return new EnumConstant (v, result_type);
244 } else if (left is UIntConstant){
246 uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value;
248 v = new UIntConstant (res, left.Location);
249 if (result_type == null)
252 return new EnumConstant (v, result_type);
253 } else if (left is LongConstant){
255 long res = ((LongConstant)left).Value | ((LongConstant)right).Value;
257 v = new LongConstant (res, left.Location);
258 if (result_type == null)
261 return new EnumConstant (v, result_type);
262 } else if (left is ULongConstant){
264 ulong res = ((ULongConstant)left).Value |
265 ((ULongConstant)right).Value;
267 v = new ULongConstant (res, left.Location);
268 if (result_type == null)
271 return new EnumConstant (v, result_type);
272 } else if (left is UShortConstant){
274 ushort res = (ushort) (((UShortConstant)left).Value |
275 ((UShortConstant)right).Value);
277 v = new UShortConstant (res, left.Location);
278 if (result_type == null)
281 return new EnumConstant (v, result_type);
282 } else if (left is ShortConstant){
284 short res = (short) (((ShortConstant)left).Value |
285 ((ShortConstant)right).Value);
287 v = new ShortConstant (res, left.Location);
288 if (result_type == null)
291 return new EnumConstant (v, result_type);
295 case Binary.Operator.BitwiseAnd:
296 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
297 if (left == null || right == null)
300 if (left is IntConstant){
302 int res = ((IntConstant) left).Value & ((IntConstant) right).Value;
304 v = new IntConstant (res, left.Location);
305 if (result_type == null)
308 return new EnumConstant (v, result_type);
309 } else if (left is UIntConstant){
311 uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value;
313 v = new UIntConstant (res, left.Location);
314 if (result_type == null)
317 return new EnumConstant (v, result_type);
318 } else if (left is LongConstant){
320 long res = ((LongConstant)left).Value & ((LongConstant)right).Value;
322 v = new LongConstant (res, left.Location);
323 if (result_type == null)
326 return new EnumConstant (v, result_type);
327 } else if (left is ULongConstant){
329 ulong res = ((ULongConstant)left).Value &
330 ((ULongConstant)right).Value;
332 v = new ULongConstant (res, left.Location);
333 if (result_type == null)
336 return new EnumConstant (v, result_type);
337 } else if (left is UShortConstant){
339 ushort res = (ushort) (((UShortConstant)left).Value &
340 ((UShortConstant)right).Value);
342 v = new UShortConstant (res, left.Location);
343 if (result_type == null)
346 return new EnumConstant (v, result_type);
347 } else if (left is ShortConstant){
349 short res = (short) (((ShortConstant)left).Value &
350 ((ShortConstant)right).Value);
352 v = new ShortConstant (res, left.Location);
353 if (result_type == null)
356 return new EnumConstant (v, result_type);
360 case Binary.Operator.ExclusiveOr:
361 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
362 if (left == null || right == null)
365 if (left is IntConstant){
367 int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value;
369 v = new IntConstant (res, left.Location);
370 if (result_type == null)
373 return new EnumConstant (v, result_type);
374 } else if (left is UIntConstant){
376 uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value;
378 v = new UIntConstant (res, left.Location);
379 if (result_type == null)
382 return new EnumConstant (v, result_type);
383 } else if (left is LongConstant){
385 long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value;
387 v = new LongConstant (res, left.Location);
388 if (result_type == null)
391 return new EnumConstant (v, result_type);
392 } else if (left is ULongConstant){
394 ulong res = ((ULongConstant)left).Value ^
395 ((ULongConstant)right).Value;
397 v = new ULongConstant (res, left.Location);
398 if (result_type == null)
401 return new EnumConstant (v, result_type);
402 } else if (left is UShortConstant){
404 ushort res = (ushort) (((UShortConstant)left).Value ^
405 ((UShortConstant)right).Value);
407 v = new UShortConstant (res, left.Location);
408 if (result_type == null)
411 return new EnumConstant (v, result_type);
412 } else if (left is ShortConstant){
414 short res = (short)(((ShortConstant)left).Value ^
415 ((ShortConstant)right).Value);
417 v = new ShortConstant (res, left.Location);
418 if (result_type == null)
421 return new EnumConstant (v, result_type);
425 case Binary.Operator.Addition:
426 bool left_is_string = left is StringConstant;
427 bool right_is_string = right is StringConstant;
430 // If both sides are strings, then concatenate, if
431 // one is a string, and the other is not, then defer
432 // to runtime concatenation
435 if (left_is_string || right_is_string){
436 if (left_is_string && right_is_string)
437 return new StringConstant (
438 ((StringConstant) left).Value +
439 ((StringConstant) right).Value, left.Location);
445 // handle "E operator + (E x, U y)"
446 // handle "E operator + (Y y, E x)"
448 // note that E operator + (E x, E y) is invalid
450 if (left is EnumConstant){
451 if (right is EnumConstant){
455 right = right.ToType (((EnumConstant) left).Child.Type);
460 } else if (right is EnumConstant){
461 left = left.ToType (((EnumConstant) right).Child.Type);
465 wrap_as = right.Type;
469 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
470 if (left == null || right == null)
474 if (left is DoubleConstant){
477 if (ec.ConstantCheckState)
478 res = checked (((DoubleConstant) left).Value +
479 ((DoubleConstant) right).Value);
481 res = unchecked (((DoubleConstant) left).Value +
482 ((DoubleConstant) right).Value);
484 result = new DoubleConstant (res, left.Location);
485 } else if (left is FloatConstant){
488 if (ec.ConstantCheckState)
489 res = checked (((FloatConstant) left).Value +
490 ((FloatConstant) right).Value);
492 res = unchecked (((FloatConstant) left).Value +
493 ((FloatConstant) right).Value);
495 result = new FloatConstant (res, left.Location);
496 } else if (left is ULongConstant){
499 if (ec.ConstantCheckState)
500 res = checked (((ULongConstant) left).Value +
501 ((ULongConstant) right).Value);
503 res = unchecked (((ULongConstant) left).Value +
504 ((ULongConstant) right).Value);
506 result = new ULongConstant (res, left.Location);
507 } else if (left is LongConstant){
510 if (ec.ConstantCheckState)
511 res = checked (((LongConstant) left).Value +
512 ((LongConstant) right).Value);
514 res = unchecked (((LongConstant) left).Value +
515 ((LongConstant) right).Value);
517 result = new LongConstant (res, left.Location);
518 } else if (left is UIntConstant){
521 if (ec.ConstantCheckState)
522 res = checked (((UIntConstant) left).Value +
523 ((UIntConstant) right).Value);
525 res = unchecked (((UIntConstant) left).Value +
526 ((UIntConstant) right).Value);
528 result = new UIntConstant (res, left.Location);
529 } else if (left is IntConstant){
532 if (ec.ConstantCheckState)
533 res = checked (((IntConstant) left).Value +
534 ((IntConstant) right).Value);
536 res = unchecked (((IntConstant) left).Value +
537 ((IntConstant) right).Value);
539 result = new IntConstant (res, left.Location);
540 } else if (left is DecimalConstant) {
543 if (ec.ConstantCheckState)
544 res = checked (((DecimalConstant) left).Value +
545 ((DecimalConstant) right).Value);
547 res = unchecked (((DecimalConstant) left).Value +
548 ((DecimalConstant) right).Value);
550 result = new DecimalConstant (res, left.Location);
552 throw new Exception ( "Unexepected addition input: " + left);
554 } catch (OverflowException){
555 Error_CompileTimeOverflow (loc);
558 if (wrap_as != null) {
560 return result.TryReduce (ec, wrap_as, loc);
562 catch (OverflowException) {
569 case Binary.Operator.Subtraction:
571 // handle "E operator - (E x, U y)"
572 // handle "E operator - (Y y, E x)"
573 // handle "U operator - (E x, E y)"
576 if (left is EnumConstant){
577 if (right is EnumConstant){
578 if (left.Type != right.Type) {
579 Binary.Error_OperatorCannotBeApplied (loc, "-", left.Type, right.Type);
583 wrap_as = TypeManager.EnumToUnderlying (left.Type);
584 right = ((EnumConstant) right).Child.ToType (wrap_as);
588 left = ((EnumConstant) left).Child.ToType (wrap_as);
593 right = right.ToType (((EnumConstant) left).Child.Type);
599 } else if (right is EnumConstant){
600 left = left.ToType (((EnumConstant) right).Child.Type);
604 wrap_as = right.Type;
607 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
608 if (left == null || right == null)
612 if (left is DoubleConstant){
615 if (ec.ConstantCheckState)
616 res = checked (((DoubleConstant) left).Value -
617 ((DoubleConstant) right).Value);
619 res = unchecked (((DoubleConstant) left).Value -
620 ((DoubleConstant) right).Value);
622 result = new DoubleConstant (res, left.Location);
623 } else if (left is FloatConstant){
626 if (ec.ConstantCheckState)
627 res = checked (((FloatConstant) left).Value -
628 ((FloatConstant) right).Value);
630 res = unchecked (((FloatConstant) left).Value -
631 ((FloatConstant) right).Value);
633 result = new FloatConstant (res, left.Location);
634 } else if (left is ULongConstant){
637 if (ec.ConstantCheckState)
638 res = checked (((ULongConstant) left).Value -
639 ((ULongConstant) right).Value);
641 res = unchecked (((ULongConstant) left).Value -
642 ((ULongConstant) right).Value);
644 result = new ULongConstant (res, left.Location);
645 } else if (left is LongConstant){
648 if (ec.ConstantCheckState)
649 res = checked (((LongConstant) left).Value -
650 ((LongConstant) right).Value);
652 res = unchecked (((LongConstant) left).Value -
653 ((LongConstant) right).Value);
655 result = new LongConstant (res, left.Location);
656 } else if (left is UIntConstant){
659 if (ec.ConstantCheckState)
660 res = checked (((UIntConstant) left).Value -
661 ((UIntConstant) right).Value);
663 res = unchecked (((UIntConstant) left).Value -
664 ((UIntConstant) right).Value);
666 result = new UIntConstant (res, left.Location);
667 } else if (left is IntConstant){
670 if (ec.ConstantCheckState)
671 res = checked (((IntConstant) left).Value -
672 ((IntConstant) right).Value);
674 res = unchecked (((IntConstant) left).Value -
675 ((IntConstant) right).Value);
677 result = new IntConstant (res, left.Location);
678 } else if (left is DecimalConstant) {
681 if (ec.ConstantCheckState)
682 res = checked (((DecimalConstant) left).Value -
683 ((DecimalConstant) right).Value);
685 res = unchecked (((DecimalConstant) left).Value -
686 ((DecimalConstant) right).Value);
688 return new DecimalConstant (res, left.Location);
690 throw new Exception ( "Unexepected subtraction input: " + left);
692 } catch (OverflowException){
693 Error_CompileTimeOverflow (loc);
696 if (wrap_as != null) {
698 return result.TryReduce (ec, wrap_as, loc);
700 catch (OverflowException) {
707 case Binary.Operator.Multiply:
708 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
709 if (left == null || right == null)
713 if (left is DoubleConstant){
716 if (ec.ConstantCheckState)
717 res = checked (((DoubleConstant) left).Value *
718 ((DoubleConstant) right).Value);
720 res = unchecked (((DoubleConstant) left).Value *
721 ((DoubleConstant) right).Value);
723 return new DoubleConstant (res, left.Location);
724 } else if (left is FloatConstant){
727 if (ec.ConstantCheckState)
728 res = checked (((FloatConstant) left).Value *
729 ((FloatConstant) right).Value);
731 res = unchecked (((FloatConstant) left).Value *
732 ((FloatConstant) right).Value);
734 return new FloatConstant (res, left.Location);
735 } else if (left is ULongConstant){
738 if (ec.ConstantCheckState)
739 res = checked (((ULongConstant) left).Value *
740 ((ULongConstant) right).Value);
742 res = unchecked (((ULongConstant) left).Value *
743 ((ULongConstant) right).Value);
745 return new ULongConstant (res, left.Location);
746 } else if (left is LongConstant){
749 if (ec.ConstantCheckState)
750 res = checked (((LongConstant) left).Value *
751 ((LongConstant) right).Value);
753 res = unchecked (((LongConstant) left).Value *
754 ((LongConstant) right).Value);
756 return new LongConstant (res, left.Location);
757 } else if (left is UIntConstant){
760 if (ec.ConstantCheckState)
761 res = checked (((UIntConstant) left).Value *
762 ((UIntConstant) right).Value);
764 res = unchecked (((UIntConstant) left).Value *
765 ((UIntConstant) right).Value);
767 return new UIntConstant (res, left.Location);
768 } else if (left is IntConstant){
771 if (ec.ConstantCheckState)
772 res = checked (((IntConstant) left).Value *
773 ((IntConstant) right).Value);
775 res = unchecked (((IntConstant) left).Value *
776 ((IntConstant) right).Value);
778 return new IntConstant (res, left.Location);
779 } else if (left is DecimalConstant) {
782 if (ec.ConstantCheckState)
783 res = checked (((DecimalConstant) left).Value *
784 ((DecimalConstant) right).Value);
786 res = unchecked (((DecimalConstant) left).Value *
787 ((DecimalConstant) right).Value);
789 return new DecimalConstant (res, left.Location);
791 throw new Exception ( "Unexepected multiply input: " + left);
793 } catch (OverflowException){
794 Error_CompileTimeOverflow (loc);
798 case Binary.Operator.Division:
799 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
800 if (left == null || right == null)
804 if (left is DoubleConstant){
807 if (ec.ConstantCheckState)
808 res = checked (((DoubleConstant) left).Value /
809 ((DoubleConstant) right).Value);
811 res = unchecked (((DoubleConstant) left).Value /
812 ((DoubleConstant) right).Value);
814 return new DoubleConstant (res, left.Location);
815 } else if (left is FloatConstant){
818 if (ec.ConstantCheckState)
819 res = checked (((FloatConstant) left).Value /
820 ((FloatConstant) right).Value);
822 res = unchecked (((FloatConstant) left).Value /
823 ((FloatConstant) right).Value);
825 return new FloatConstant (res, left.Location);
826 } else if (left is ULongConstant){
829 if (ec.ConstantCheckState)
830 res = checked (((ULongConstant) left).Value /
831 ((ULongConstant) right).Value);
833 res = unchecked (((ULongConstant) left).Value /
834 ((ULongConstant) right).Value);
836 return new ULongConstant (res, left.Location);
837 } else if (left is LongConstant){
840 if (ec.ConstantCheckState)
841 res = checked (((LongConstant) left).Value /
842 ((LongConstant) right).Value);
844 res = unchecked (((LongConstant) left).Value /
845 ((LongConstant) right).Value);
847 return new LongConstant (res, left.Location);
848 } else if (left is UIntConstant){
851 if (ec.ConstantCheckState)
852 res = checked (((UIntConstant) left).Value /
853 ((UIntConstant) right).Value);
855 res = unchecked (((UIntConstant) left).Value /
856 ((UIntConstant) right).Value);
858 return new UIntConstant (res, left.Location);
859 } else if (left is IntConstant){
862 if (ec.ConstantCheckState)
863 res = checked (((IntConstant) left).Value /
864 ((IntConstant) right).Value);
866 res = unchecked (((IntConstant) left).Value /
867 ((IntConstant) right).Value);
869 return new IntConstant (res, left.Location);
870 } else if (left is DecimalConstant) {
873 if (ec.ConstantCheckState)
874 res = checked (((DecimalConstant) left).Value /
875 ((DecimalConstant) right).Value);
877 res = unchecked (((DecimalConstant) left).Value /
878 ((DecimalConstant) right).Value);
880 return new DecimalConstant (res, left.Location);
882 throw new Exception ( "Unexepected division input: " + left);
884 } catch (OverflowException){
885 Error_CompileTimeOverflow (loc);
887 } catch (DivideByZeroException) {
888 Report.Error (020, loc, "Division by constant zero");
893 case Binary.Operator.Modulus:
894 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
895 if (left == null || right == null)
899 if (left is DoubleConstant){
902 if (ec.ConstantCheckState)
903 res = checked (((DoubleConstant) left).Value %
904 ((DoubleConstant) right).Value);
906 res = unchecked (((DoubleConstant) left).Value %
907 ((DoubleConstant) right).Value);
909 return new DoubleConstant (res, left.Location);
910 } else if (left is FloatConstant){
913 if (ec.ConstantCheckState)
914 res = checked (((FloatConstant) left).Value %
915 ((FloatConstant) right).Value);
917 res = unchecked (((FloatConstant) left).Value %
918 ((FloatConstant) right).Value);
920 return new FloatConstant (res, left.Location);
921 } else if (left is ULongConstant){
924 if (ec.ConstantCheckState)
925 res = checked (((ULongConstant) left).Value %
926 ((ULongConstant) right).Value);
928 res = unchecked (((ULongConstant) left).Value %
929 ((ULongConstant) right).Value);
931 return new ULongConstant (res, left.Location);
932 } else if (left is LongConstant){
935 if (ec.ConstantCheckState)
936 res = checked (((LongConstant) left).Value %
937 ((LongConstant) right).Value);
939 res = unchecked (((LongConstant) left).Value %
940 ((LongConstant) right).Value);
942 return new LongConstant (res, left.Location);
943 } else if (left is UIntConstant){
946 if (ec.ConstantCheckState)
947 res = checked (((UIntConstant) left).Value %
948 ((UIntConstant) right).Value);
950 res = unchecked (((UIntConstant) left).Value %
951 ((UIntConstant) right).Value);
953 return new UIntConstant (res, left.Location);
954 } else if (left is IntConstant){
957 if (ec.ConstantCheckState)
958 res = checked (((IntConstant) left).Value %
959 ((IntConstant) right).Value);
961 res = unchecked (((IntConstant) left).Value %
962 ((IntConstant) right).Value);
964 return new IntConstant (res, left.Location);
966 throw new Exception ( "Unexepected modulus input: " + left);
968 } catch (DivideByZeroException){
969 Report.Error (020, loc, "Division by constant zero");
970 } catch (OverflowException){
971 Error_CompileTimeOverflow (loc);
976 // There is no overflow checking on left shift
978 case Binary.Operator.LeftShift:
979 IntConstant ic = right.ToInt (loc);
981 Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
984 int lshift_val = ic.Value;
987 if ((lic = left.ConvertToInt ()) != null)
988 return new IntConstant (lic.Value << lshift_val, left.Location);
991 if ((luic = left.ConvertToUInt ()) != null)
992 return new UIntConstant (luic.Value << lshift_val, left.Location);
995 if ((llc = left.ConvertToLong ()) != null)
996 return new LongConstant (llc.Value << lshift_val, left.Location);
999 if ((lulc = left.ConvertToULong ()) != null)
1000 return new ULongConstant (lulc.Value << lshift_val, left.Location);
1002 Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
1006 // There is no overflow checking on right shift
1008 case Binary.Operator.RightShift:
1009 IntConstant sic = right.ToInt (loc);
1011 Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
1014 int rshift_val = sic.Value;
1017 if ((ric = left.ConvertToInt ()) != null)
1018 return new IntConstant (ric.Value >> rshift_val, left.Location);
1021 if ((ruic = left.ConvertToUInt ()) != null)
1022 return new UIntConstant (ruic.Value >> rshift_val, left.Location);
1025 if ((rlc = left.ConvertToLong ()) != null)
1026 return new LongConstant (rlc.Value >> rshift_val, left.Location);
1029 if ((rulc = left.ConvertToULong ()) != null)
1030 return new ULongConstant (rulc.Value >> rshift_val, left.Location);
1032 Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
1035 case Binary.Operator.Equality:
1036 if (left is NullConstant){
1037 if (right is NullConstant)
1038 return new BoolConstant (true, left.Location);
1039 else if (right is StringConstant)
1040 return new BoolConstant (
1041 ((StringConstant) right).Value == null, left.Location);
1042 } else if (right is NullConstant){
1043 if (left is NullConstant)
1044 return new BoolConstant (true, left.Location);
1045 else if (left is StringConstant)
1046 return new BoolConstant (
1047 ((StringConstant) left).Value == null, left.Location);
1049 if (left is StringConstant && right is StringConstant){
1050 return new BoolConstant (
1051 ((StringConstant) left).Value ==
1052 ((StringConstant) right).Value, left.Location);
1056 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1057 if (left == null || right == null)
1061 if (left is DoubleConstant)
1062 bool_res = ((DoubleConstant) left).Value ==
1063 ((DoubleConstant) right).Value;
1064 else if (left is FloatConstant)
1065 bool_res = ((FloatConstant) left).Value ==
1066 ((FloatConstant) right).Value;
1067 else if (left is ULongConstant)
1068 bool_res = ((ULongConstant) left).Value ==
1069 ((ULongConstant) right).Value;
1070 else if (left is LongConstant)
1071 bool_res = ((LongConstant) left).Value ==
1072 ((LongConstant) right).Value;
1073 else if (left is UIntConstant)
1074 bool_res = ((UIntConstant) left).Value ==
1075 ((UIntConstant) right).Value;
1076 else if (left is IntConstant)
1077 bool_res = ((IntConstant) left).Value ==
1078 ((IntConstant) right).Value;
1082 return new BoolConstant (bool_res, left.Location);
1084 case Binary.Operator.Inequality:
1085 if (left is NullConstant){
1086 if (right is NullConstant)
1087 return new BoolConstant (false, left.Location);
1088 else if (right is StringConstant)
1089 return new BoolConstant (
1090 ((StringConstant) right).Value != null, left.Location);
1091 } else if (right is NullConstant){
1092 if (left is NullConstant)
1093 return new BoolConstant (false, left.Location);
1094 else if (left is StringConstant)
1095 return new BoolConstant (
1096 ((StringConstant) left).Value != null, left.Location);
1098 if (left is StringConstant && right is StringConstant){
1099 return new BoolConstant (
1100 ((StringConstant) left).Value !=
1101 ((StringConstant) right).Value, left.Location);
1104 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1105 if (left == null || right == null)
1109 if (left is DoubleConstant)
1110 bool_res = ((DoubleConstant) left).Value !=
1111 ((DoubleConstant) right).Value;
1112 else if (left is FloatConstant)
1113 bool_res = ((FloatConstant) left).Value !=
1114 ((FloatConstant) right).Value;
1115 else if (left is ULongConstant)
1116 bool_res = ((ULongConstant) left).Value !=
1117 ((ULongConstant) right).Value;
1118 else if (left is LongConstant)
1119 bool_res = ((LongConstant) left).Value !=
1120 ((LongConstant) right).Value;
1121 else if (left is UIntConstant)
1122 bool_res = ((UIntConstant) left).Value !=
1123 ((UIntConstant) right).Value;
1124 else if (left is IntConstant)
1125 bool_res = ((IntConstant) left).Value !=
1126 ((IntConstant) right).Value;
1130 return new BoolConstant (bool_res, left.Location);
1132 case Binary.Operator.LessThan:
1133 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1134 if (left == null || right == null)
1138 if (left is DoubleConstant)
1139 bool_res = ((DoubleConstant) left).Value <
1140 ((DoubleConstant) right).Value;
1141 else if (left is FloatConstant)
1142 bool_res = ((FloatConstant) left).Value <
1143 ((FloatConstant) right).Value;
1144 else if (left is ULongConstant)
1145 bool_res = ((ULongConstant) left).Value <
1146 ((ULongConstant) right).Value;
1147 else if (left is LongConstant)
1148 bool_res = ((LongConstant) left).Value <
1149 ((LongConstant) right).Value;
1150 else if (left is UIntConstant)
1151 bool_res = ((UIntConstant) left).Value <
1152 ((UIntConstant) right).Value;
1153 else if (left is IntConstant)
1154 bool_res = ((IntConstant) left).Value <
1155 ((IntConstant) right).Value;
1159 return new BoolConstant (bool_res, left.Location);
1161 case Binary.Operator.GreaterThan:
1162 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1163 if (left == null || right == null)
1167 if (left is DoubleConstant)
1168 bool_res = ((DoubleConstant) left).Value >
1169 ((DoubleConstant) right).Value;
1170 else if (left is FloatConstant)
1171 bool_res = ((FloatConstant) left).Value >
1172 ((FloatConstant) right).Value;
1173 else if (left is ULongConstant)
1174 bool_res = ((ULongConstant) left).Value >
1175 ((ULongConstant) right).Value;
1176 else if (left is LongConstant)
1177 bool_res = ((LongConstant) left).Value >
1178 ((LongConstant) right).Value;
1179 else if (left is UIntConstant)
1180 bool_res = ((UIntConstant) left).Value >
1181 ((UIntConstant) right).Value;
1182 else if (left is IntConstant)
1183 bool_res = ((IntConstant) left).Value >
1184 ((IntConstant) right).Value;
1188 return new BoolConstant (bool_res, left.Location);
1190 case Binary.Operator.GreaterThanOrEqual:
1191 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1192 if (left == null || right == null)
1196 if (left is DoubleConstant)
1197 bool_res = ((DoubleConstant) left).Value >=
1198 ((DoubleConstant) right).Value;
1199 else if (left is FloatConstant)
1200 bool_res = ((FloatConstant) left).Value >=
1201 ((FloatConstant) right).Value;
1202 else if (left is ULongConstant)
1203 bool_res = ((ULongConstant) left).Value >=
1204 ((ULongConstant) right).Value;
1205 else if (left is LongConstant)
1206 bool_res = ((LongConstant) left).Value >=
1207 ((LongConstant) right).Value;
1208 else if (left is UIntConstant)
1209 bool_res = ((UIntConstant) left).Value >=
1210 ((UIntConstant) right).Value;
1211 else if (left is IntConstant)
1212 bool_res = ((IntConstant) left).Value >=
1213 ((IntConstant) right).Value;
1217 return new BoolConstant (bool_res, left.Location);
1219 case Binary.Operator.LessThanOrEqual:
1220 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1221 if (left == null || right == null)
1225 if (left is DoubleConstant)
1226 bool_res = ((DoubleConstant) left).Value <=
1227 ((DoubleConstant) right).Value;
1228 else if (left is FloatConstant)
1229 bool_res = ((FloatConstant) left).Value <=
1230 ((FloatConstant) right).Value;
1231 else if (left is ULongConstant)
1232 bool_res = ((ULongConstant) left).Value <=
1233 ((ULongConstant) right).Value;
1234 else if (left is LongConstant)
1235 bool_res = ((LongConstant) left).Value <=
1236 ((LongConstant) right).Value;
1237 else if (left is UIntConstant)
1238 bool_res = ((UIntConstant) left).Value <=
1239 ((UIntConstant) right).Value;
1240 else if (left is IntConstant)
1241 bool_res = ((IntConstant) left).Value <=
1242 ((IntConstant) right).Value;
1246 return new BoolConstant (bool_res, left.Location);