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
);
123 right
= new UIntConstant ((uint) ic
.Value
);
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
){
145 // If either operand is an enum constant, the other one must
146 // be implicitly convertable to that enum's underlying type.
150 if (left
is EnumConstant
){
152 match
= (EnumConstant
) left
;
155 match
= (EnumConstant
) right
;
158 bool need_check
= (other
is EnumConstant
) ||
159 ((oper
!= Binary
.Operator
.Addition
) &&
160 (oper
!= Binary
.Operator
.Subtraction
));
163 !Convert
.WideningConversionExists (ec
, match
, other
.Type
)) {
164 Convert
.Error_CannotWideningConversion (loc
, match
.Type
, other
.Type
);
170 if (left
is EnumConstant
)
171 left
= ((EnumConstant
) left
).Child
;
172 if (right
is EnumConstant
)
173 right
= ((EnumConstant
) right
).Child
;
175 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
180 // Force conversions to int32
182 if (!(left
is IntConstant
))
183 left
= left
.ToInt (loc
);
184 if (!(right
is IntConstant
))
185 right
= right
.ToInt (loc
);
190 static void Error_CompileTimeOverflow (Location loc
)
192 Report
.Error (220, loc
, "The operation overflows at compile time in checked mode");
196 /// Constant expression folder for binary operations.
198 /// Returns null if the expression can not be folded.
200 static public Expression
BinaryFold (EmitContext ec
, Binary
.Operator oper
,
201 Constant left
, Constant right
, Location loc
)
204 Type rt
= right
.Type
;
205 Type result_type
= null;
209 // Enumerator folding
211 if (rt
== lt
&& left
is EnumConstant
)
215 // During an enum evaluation, we need to unwrap enumerations
217 if (ec
.InEnumContext
){
218 if (left
is EnumConstant
)
219 left
= ((EnumConstant
) left
).Child
;
221 if (right
is EnumConstant
)
222 right
= ((EnumConstant
) right
).Child
;
226 Constant result
= null;
228 case Binary
.Operator
.BitwiseOr
:
229 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
230 if (left
== null || right
== null)
233 if (left
is IntConstant
){
235 int res
= ((IntConstant
) left
).Value
| ((IntConstant
) right
).Value
;
237 v
= new IntConstant (res
);
238 if (result_type
== null)
241 return new EnumConstant (v
, result_type
);
242 } else if (left
is UIntConstant
){
244 uint res
= ((UIntConstant
)left
).Value
| ((UIntConstant
)right
).Value
;
246 v
= new UIntConstant (res
);
247 if (result_type
== null)
250 return new EnumConstant (v
, result_type
);
251 } else if (left
is LongConstant
){
253 long res
= ((LongConstant
)left
).Value
| ((LongConstant
)right
).Value
;
255 v
= new LongConstant (res
);
256 if (result_type
== null)
259 return new EnumConstant (v
, result_type
);
260 } else if (left
is ULongConstant
){
262 ulong res
= ((ULongConstant
)left
).Value
|
263 ((ULongConstant
)right
).Value
;
265 v
= new ULongConstant (res
);
266 if (result_type
== null)
269 return new EnumConstant (v
, result_type
);
270 } else if (left
is UShortConstant
){
272 ushort res
= (ushort) (((UShortConstant
)left
).Value
|
273 ((UShortConstant
)right
).Value
);
275 v
= new UShortConstant (res
);
276 if (result_type
== null)
279 return new EnumConstant (v
, result_type
);
280 } else if (left
is ShortConstant
){
282 short res
= (short) (((ShortConstant
)left
).Value
|
283 ((ShortConstant
)right
).Value
);
285 v
= new ShortConstant (res
);
286 if (result_type
== null)
289 return new EnumConstant (v
, result_type
);
293 case Binary
.Operator
.BitwiseAnd
:
294 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
295 if (left
== null || right
== null)
298 if (left
is IntConstant
){
300 int res
= ((IntConstant
) left
).Value
& ((IntConstant
) right
).Value
;
302 v
= new IntConstant (res
);
303 if (result_type
== null)
306 return new EnumConstant (v
, result_type
);
307 } else if (left
is UIntConstant
){
309 uint res
= ((UIntConstant
)left
).Value
& ((UIntConstant
)right
).Value
;
311 v
= new UIntConstant (res
);
312 if (result_type
== null)
315 return new EnumConstant (v
, result_type
);
316 } else if (left
is LongConstant
){
318 long res
= ((LongConstant
)left
).Value
& ((LongConstant
)right
).Value
;
320 v
= new LongConstant (res
);
321 if (result_type
== null)
324 return new EnumConstant (v
, result_type
);
325 } else if (left
is ULongConstant
){
327 ulong res
= ((ULongConstant
)left
).Value
&
328 ((ULongConstant
)right
).Value
;
330 v
= new ULongConstant (res
);
331 if (result_type
== null)
334 return new EnumConstant (v
, result_type
);
335 } else if (left
is UShortConstant
){
337 ushort res
= (ushort) (((UShortConstant
)left
).Value
&
338 ((UShortConstant
)right
).Value
);
340 v
= new UShortConstant (res
);
341 if (result_type
== null)
344 return new EnumConstant (v
, result_type
);
345 } else if (left
is ShortConstant
){
347 short res
= (short) (((ShortConstant
)left
).Value
&
348 ((ShortConstant
)right
).Value
);
350 v
= new ShortConstant (res
);
351 if (result_type
== null)
354 return new EnumConstant (v
, result_type
);
358 case Binary
.Operator
.ExclusiveOr
:
359 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
360 if (left
== null || right
== null)
363 if (left
is IntConstant
){
365 int res
= ((IntConstant
) left
).Value ^
((IntConstant
) right
).Value
;
367 v
= new IntConstant (res
);
368 if (result_type
== null)
371 return new EnumConstant (v
, result_type
);
372 } else if (left
is UIntConstant
){
374 uint res
= ((UIntConstant
)left
).Value ^
((UIntConstant
)right
).Value
;
376 v
= new UIntConstant (res
);
377 if (result_type
== null)
380 return new EnumConstant (v
, result_type
);
381 } else if (left
is LongConstant
){
383 long res
= ((LongConstant
)left
).Value ^
((LongConstant
)right
).Value
;
385 v
= new LongConstant (res
);
386 if (result_type
== null)
389 return new EnumConstant (v
, result_type
);
390 } else if (left
is ULongConstant
){
392 ulong res
= ((ULongConstant
)left
).Value ^
393 ((ULongConstant
)right
).Value
;
395 v
= new ULongConstant (res
);
396 if (result_type
== null)
399 return new EnumConstant (v
, result_type
);
400 } else if (left
is UShortConstant
){
402 ushort res
= (ushort) (((UShortConstant
)left
).Value ^
403 ((UShortConstant
)right
).Value
);
405 v
= new UShortConstant (res
);
406 if (result_type
== null)
409 return new EnumConstant (v
, result_type
);
410 } else if (left
is ShortConstant
){
412 short res
= (short)(((ShortConstant
)left
).Value ^
413 ((ShortConstant
)right
).Value
);
415 v
= new ShortConstant (res
);
416 if (result_type
== null)
419 return new EnumConstant (v
, result_type
);
423 case Binary
.Operator
.Addition
:
424 bool left_is_string
= left
is StringConstant
;
425 bool right_is_string
= right
is StringConstant
;
428 // If both sides are strings, then concatenate, if
429 // one is a string, and the other is not, then defer
430 // to runtime concatenation
433 if (left_is_string
|| right_is_string
){
434 if (left_is_string
&& right_is_string
)
435 return new StringConstant (
436 ((StringConstant
) left
).Value
+
437 ((StringConstant
) right
).Value
);
443 // handle "E operator + (E x, U y)"
444 // handle "E operator + (Y y, E x)"
446 // note that E operator + (E x, E y) is invalid
448 if (left
is EnumConstant
){
449 if (right
is EnumConstant
){
452 if (((EnumConstant
) left
).Child
.Type
!= right
.Type
)
456 } else if (right
is EnumConstant
){
457 if (((EnumConstant
) right
).Child
.Type
!= left
.Type
)
459 wrap_as
= right
.Type
;
463 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
464 if (left
== null || right
== null)
468 if (left
is DoubleConstant
){
471 if (ec
.ConstantCheckState
)
472 res
= checked (((DoubleConstant
) left
).Value
+
473 ((DoubleConstant
) right
).Value
);
475 res
= unchecked (((DoubleConstant
) left
).Value
+
476 ((DoubleConstant
) right
).Value
);
478 result
= new DoubleConstant (res
);
479 } else if (left
is FloatConstant
){
482 if (ec
.ConstantCheckState
)
483 res
= checked (((FloatConstant
) left
).Value
+
484 ((FloatConstant
) right
).Value
);
486 res
= unchecked (((FloatConstant
) left
).Value
+
487 ((FloatConstant
) right
).Value
);
489 result
= new FloatConstant (res
);
490 } else if (left
is ULongConstant
){
493 if (ec
.ConstantCheckState
)
494 res
= checked (((ULongConstant
) left
).Value
+
495 ((ULongConstant
) right
).Value
);
497 res
= unchecked (((ULongConstant
) left
).Value
+
498 ((ULongConstant
) right
).Value
);
500 result
= new ULongConstant (res
);
501 } else if (left
is LongConstant
){
504 if (ec
.ConstantCheckState
)
505 res
= checked (((LongConstant
) left
).Value
+
506 ((LongConstant
) right
).Value
);
508 res
= unchecked (((LongConstant
) left
).Value
+
509 ((LongConstant
) right
).Value
);
511 result
= new LongConstant (res
);
512 } else if (left
is UIntConstant
){
515 if (ec
.ConstantCheckState
)
516 res
= checked (((UIntConstant
) left
).Value
+
517 ((UIntConstant
) right
).Value
);
519 res
= unchecked (((UIntConstant
) left
).Value
+
520 ((UIntConstant
) right
).Value
);
522 result
= new UIntConstant (res
);
523 } else if (left
is IntConstant
){
526 if (ec
.ConstantCheckState
)
527 res
= checked (((IntConstant
) left
).Value
+
528 ((IntConstant
) right
).Value
);
530 res
= unchecked (((IntConstant
) left
).Value
+
531 ((IntConstant
) right
).Value
);
533 result
= new IntConstant (res
);
534 } else if (left
is DecimalConstant
) {
537 if (ec
.ConstantCheckState
)
538 res
= checked (((DecimalConstant
) left
).Value
+
539 ((DecimalConstant
) right
).Value
);
541 res
= unchecked (((DecimalConstant
) left
).Value
+
542 ((DecimalConstant
) right
).Value
);
544 result
= new DecimalConstant (res
);
546 throw new Exception ( "Unexepected addition input: " + left
);
548 } catch (OverflowException
){
549 Error_CompileTimeOverflow (loc
);
553 return new EnumConstant (result
, wrap_as
);
557 case Binary
.Operator
.Subtraction
:
559 // handle "E operator - (E x, U y)"
560 // handle "E operator - (Y y, E x)"
561 // handle "U operator - (E x, E y)"
564 if (left
is EnumConstant
){
565 if (right
is EnumConstant
){
566 if (left
.Type
== right
.Type
)
567 wrap_as
= TypeManager
.EnumToUnderlying (left
.Type
);
571 if (((EnumConstant
) left
).Child
.Type
!= right
.Type
)
575 } else if (right
is EnumConstant
){
576 if (((EnumConstant
) right
).Child
.Type
!= left
.Type
)
578 wrap_as
= right
.Type
;
581 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
582 if (left
== null || right
== null)
586 if (left
is DoubleConstant
){
589 if (ec
.ConstantCheckState
)
590 res
= checked (((DoubleConstant
) left
).Value
-
591 ((DoubleConstant
) right
).Value
);
593 res
= unchecked (((DoubleConstant
) left
).Value
-
594 ((DoubleConstant
) right
).Value
);
596 result
= new DoubleConstant (res
);
597 } else if (left
is FloatConstant
){
600 if (ec
.ConstantCheckState
)
601 res
= checked (((FloatConstant
) left
).Value
-
602 ((FloatConstant
) right
).Value
);
604 res
= unchecked (((FloatConstant
) left
).Value
-
605 ((FloatConstant
) right
).Value
);
607 result
= new FloatConstant (res
);
608 } else if (left
is ULongConstant
){
611 if (ec
.ConstantCheckState
)
612 res
= checked (((ULongConstant
) left
).Value
-
613 ((ULongConstant
) right
).Value
);
615 res
= unchecked (((ULongConstant
) left
).Value
-
616 ((ULongConstant
) right
).Value
);
618 result
= new ULongConstant (res
);
619 } else if (left
is LongConstant
){
622 if (ec
.ConstantCheckState
)
623 res
= checked (((LongConstant
) left
).Value
-
624 ((LongConstant
) right
).Value
);
626 res
= unchecked (((LongConstant
) left
).Value
-
627 ((LongConstant
) right
).Value
);
629 result
= new LongConstant (res
);
630 } else if (left
is UIntConstant
){
633 if (ec
.ConstantCheckState
)
634 res
= checked (((UIntConstant
) left
).Value
-
635 ((UIntConstant
) right
).Value
);
637 res
= unchecked (((UIntConstant
) left
).Value
-
638 ((UIntConstant
) right
).Value
);
640 result
= new UIntConstant (res
);
641 } else if (left
is IntConstant
){
644 if (ec
.ConstantCheckState
)
645 res
= checked (((IntConstant
) left
).Value
-
646 ((IntConstant
) right
).Value
);
648 res
= unchecked (((IntConstant
) left
).Value
-
649 ((IntConstant
) right
).Value
);
651 result
= new IntConstant (res
);
652 } else if (left
is DecimalConstant
) {
655 if (ec
.ConstantCheckState
)
656 res
= checked (((DecimalConstant
) left
).Value
-
657 ((DecimalConstant
) right
).Value
);
659 res
= unchecked (((DecimalConstant
) left
).Value
-
660 ((DecimalConstant
) right
).Value
);
662 return new DecimalConstant (res
);
664 throw new Exception ( "Unexepected subtraction input: " + left
);
666 } catch (OverflowException
){
667 Error_CompileTimeOverflow (loc
);
670 return new EnumConstant (result
, wrap_as
);
674 case Binary
.Operator
.Multiply
:
675 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
676 if (left
== null || right
== null)
680 if (left
is DoubleConstant
){
683 if (ec
.ConstantCheckState
)
684 res
= checked (((DoubleConstant
) left
).Value
*
685 ((DoubleConstant
) right
).Value
);
687 res
= unchecked (((DoubleConstant
) left
).Value
*
688 ((DoubleConstant
) right
).Value
);
690 return new DoubleConstant (res
);
691 } else if (left
is FloatConstant
){
694 if (ec
.ConstantCheckState
)
695 res
= checked (((FloatConstant
) left
).Value
*
696 ((FloatConstant
) right
).Value
);
698 res
= unchecked (((FloatConstant
) left
).Value
*
699 ((FloatConstant
) right
).Value
);
701 return new FloatConstant (res
);
702 } else if (left
is ULongConstant
){
705 if (ec
.ConstantCheckState
)
706 res
= checked (((ULongConstant
) left
).Value
*
707 ((ULongConstant
) right
).Value
);
709 res
= unchecked (((ULongConstant
) left
).Value
*
710 ((ULongConstant
) right
).Value
);
712 return new ULongConstant (res
);
713 } else if (left
is LongConstant
){
716 if (ec
.ConstantCheckState
)
717 res
= checked (((LongConstant
) left
).Value
*
718 ((LongConstant
) right
).Value
);
720 res
= unchecked (((LongConstant
) left
).Value
*
721 ((LongConstant
) right
).Value
);
723 return new LongConstant (res
);
724 } else if (left
is UIntConstant
){
727 if (ec
.ConstantCheckState
)
728 res
= checked (((UIntConstant
) left
).Value
*
729 ((UIntConstant
) right
).Value
);
731 res
= unchecked (((UIntConstant
) left
).Value
*
732 ((UIntConstant
) right
).Value
);
734 return new UIntConstant (res
);
735 } else if (left
is IntConstant
){
738 if (ec
.ConstantCheckState
)
739 res
= checked (((IntConstant
) left
).Value
*
740 ((IntConstant
) right
).Value
);
742 res
= unchecked (((IntConstant
) left
).Value
*
743 ((IntConstant
) right
).Value
);
745 return new IntConstant (res
);
746 } else if (left
is DecimalConstant
) {
749 if (ec
.ConstantCheckState
)
750 res
= checked (((DecimalConstant
) left
).Value
*
751 ((DecimalConstant
) right
).Value
);
753 res
= unchecked (((DecimalConstant
) left
).Value
*
754 ((DecimalConstant
) right
).Value
);
756 return new DecimalConstant (res
);
758 throw new Exception ( "Unexepected multiply input: " + left
);
760 } catch (OverflowException
){
761 Error_CompileTimeOverflow (loc
);
765 case Binary
.Operator
.Division
:
766 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
767 if (left
== null || right
== null)
771 if (left
is DoubleConstant
){
774 if (ec
.ConstantCheckState
)
775 res
= checked (((DoubleConstant
) left
).Value
/
776 ((DoubleConstant
) right
).Value
);
778 res
= unchecked (((DoubleConstant
) left
).Value
/
779 ((DoubleConstant
) right
).Value
);
781 return new DoubleConstant (res
);
782 } else if (left
is FloatConstant
){
785 if (ec
.ConstantCheckState
)
786 res
= checked (((FloatConstant
) left
).Value
/
787 ((FloatConstant
) right
).Value
);
789 res
= unchecked (((FloatConstant
) left
).Value
/
790 ((FloatConstant
) right
).Value
);
792 return new FloatConstant (res
);
793 } else if (left
is ULongConstant
){
796 if (ec
.ConstantCheckState
)
797 res
= checked (((ULongConstant
) left
).Value
/
798 ((ULongConstant
) right
).Value
);
800 res
= unchecked (((ULongConstant
) left
).Value
/
801 ((ULongConstant
) right
).Value
);
803 return new ULongConstant (res
);
804 } else if (left
is LongConstant
){
807 if (ec
.ConstantCheckState
)
808 res
= checked (((LongConstant
) left
).Value
/
809 ((LongConstant
) right
).Value
);
811 res
= unchecked (((LongConstant
) left
).Value
/
812 ((LongConstant
) right
).Value
);
814 return new LongConstant (res
);
815 } else if (left
is UIntConstant
){
818 if (ec
.ConstantCheckState
)
819 res
= checked (((UIntConstant
) left
).Value
/
820 ((UIntConstant
) right
).Value
);
822 res
= unchecked (((UIntConstant
) left
).Value
/
823 ((UIntConstant
) right
).Value
);
825 return new UIntConstant (res
);
826 } else if (left
is IntConstant
){
829 if (ec
.ConstantCheckState
)
830 res
= checked (((IntConstant
) left
).Value
/
831 ((IntConstant
) right
).Value
);
833 res
= unchecked (((IntConstant
) left
).Value
/
834 ((IntConstant
) right
).Value
);
836 return new IntConstant (res
);
837 } else if (left
is DecimalConstant
) {
840 if (ec
.ConstantCheckState
)
841 res
= checked (((DecimalConstant
) left
).Value
/
842 ((DecimalConstant
) right
).Value
);
844 res
= unchecked (((DecimalConstant
) left
).Value
/
845 ((DecimalConstant
) right
).Value
);
847 return new DecimalConstant (res
);
849 throw new Exception ( "Unexepected division input: " + left
);
851 } catch (OverflowException
){
852 Error_CompileTimeOverflow (loc
);
854 } catch (DivideByZeroException
) {
855 Report
.Error (020, loc
, "Division by constant zero");
860 case Binary
.Operator
.Modulus
:
861 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
862 if (left
== null || right
== null)
866 if (left
is DoubleConstant
){
869 if (ec
.ConstantCheckState
)
870 res
= checked (((DoubleConstant
) left
).Value
%
871 ((DoubleConstant
) right
).Value
);
873 res
= unchecked (((DoubleConstant
) left
).Value
%
874 ((DoubleConstant
) right
).Value
);
876 return new DoubleConstant (res
);
877 } else if (left
is FloatConstant
){
880 if (ec
.ConstantCheckState
)
881 res
= checked (((FloatConstant
) left
).Value
%
882 ((FloatConstant
) right
).Value
);
884 res
= unchecked (((FloatConstant
) left
).Value
%
885 ((FloatConstant
) right
).Value
);
887 return new FloatConstant (res
);
888 } else if (left
is ULongConstant
){
891 if (ec
.ConstantCheckState
)
892 res
= checked (((ULongConstant
) left
).Value
%
893 ((ULongConstant
) right
).Value
);
895 res
= unchecked (((ULongConstant
) left
).Value
%
896 ((ULongConstant
) right
).Value
);
898 return new ULongConstant (res
);
899 } else if (left
is LongConstant
){
902 if (ec
.ConstantCheckState
)
903 res
= checked (((LongConstant
) left
).Value
%
904 ((LongConstant
) right
).Value
);
906 res
= unchecked (((LongConstant
) left
).Value
%
907 ((LongConstant
) right
).Value
);
909 return new LongConstant (res
);
910 } else if (left
is UIntConstant
){
913 if (ec
.ConstantCheckState
)
914 res
= checked (((UIntConstant
) left
).Value
%
915 ((UIntConstant
) right
).Value
);
917 res
= unchecked (((UIntConstant
) left
).Value
%
918 ((UIntConstant
) right
).Value
);
920 return new UIntConstant (res
);
921 } else if (left
is IntConstant
){
924 if (ec
.ConstantCheckState
)
925 res
= checked (((IntConstant
) left
).Value
%
926 ((IntConstant
) right
).Value
);
928 res
= unchecked (((IntConstant
) left
).Value
%
929 ((IntConstant
) right
).Value
);
931 return new IntConstant (res
);
933 throw new Exception ( "Unexepected modulus input: " + left
);
935 } catch (DivideByZeroException
){
936 Report
.Error (020, loc
, "Division by constant zero");
937 } catch (OverflowException
){
938 Error_CompileTimeOverflow (loc
);
943 // There is no overflow checking on left shift
945 case Binary
.Operator
.LeftShift
:
946 IntConstant ic
= right
.ToInt (loc
);
948 Binary
.Error_OperatorCannotBeApplied (loc
, "<<", lt
, rt
);
951 int lshift_val
= ic
.Value
;
954 if ((lic
= left
.ConvertToInt ()) != null)
955 return new IntConstant (lic
.Value
<< lshift_val
);
958 if ((luic
= left
.ConvertToUInt ()) != null)
959 return new UIntConstant (luic
.Value
<< lshift_val
);
962 if ((llc
= left
.ConvertToLong ()) != null)
963 return new LongConstant (llc
.Value
<< lshift_val
);
966 if ((lulc
= left
.ConvertToULong ()) != null)
967 return new ULongConstant (lulc
.Value
<< lshift_val
);
969 Binary
.Error_OperatorCannotBeApplied (loc
, "<<", lt
, rt
);
973 // There is no overflow checking on right shift
975 case Binary
.Operator
.RightShift
:
976 IntConstant sic
= right
.ToInt (loc
);
978 Binary
.Error_OperatorCannotBeApplied (loc
, ">>", lt
, rt
);
981 int rshift_val
= sic
.Value
;
984 if ((ric
= left
.ConvertToInt ()) != null)
985 return new IntConstant (ric
.Value
>> rshift_val
);
988 if ((ruic
= left
.ConvertToUInt ()) != null)
989 return new UIntConstant (ruic
.Value
>> rshift_val
);
992 if ((rlc
= left
.ConvertToLong ()) != null)
993 return new LongConstant (rlc
.Value
>> rshift_val
);
996 if ((rulc
= left
.ConvertToULong ()) != null)
997 return new ULongConstant (rulc
.Value
>> rshift_val
);
999 Binary
.Error_OperatorCannotBeApplied (loc
, ">>", lt
, rt
);
1002 case Binary
.Operator
.LogicalAndAlso
:
1003 if (left
is BoolConstant
&& right
is BoolConstant
){
1004 return new BoolConstant (
1005 ((BoolConstant
) left
).Value
&&
1006 ((BoolConstant
) right
).Value
);
1010 case Binary
.Operator
.LogicalOrElse
:
1011 if (left
is BoolConstant
&& right
is BoolConstant
){
1012 return new BoolConstant (
1013 ((BoolConstant
) left
).Value
||
1014 ((BoolConstant
) right
).Value
);
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
);
1025 if (left
is NullLiteral
){
1026 if (right
is NullLiteral
)
1027 return new BoolConstant (true);
1028 else if (right
is StringConstant
)
1029 return new BoolConstant (
1030 ((StringConstant
) right
).Value
== null);
1031 } else if (right
is NullLiteral
){
1032 if (left
is NullLiteral
)
1033 return new BoolConstant (true);
1034 else if (left
is StringConstant
)
1035 return new BoolConstant (
1036 ((StringConstant
) left
).Value
== null);
1038 if (left
is StringConstant
&& right
is StringConstant
){
1039 return new BoolConstant (
1040 ((StringConstant
) left
).Value
==
1041 ((StringConstant
) right
).Value
);
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
);
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
);
1079 if (left
is NullLiteral
){
1080 if (right
is NullLiteral
)
1081 return new BoolConstant (false);
1082 else if (right
is StringConstant
)
1083 return new BoolConstant (
1084 ((StringConstant
) right
).Value
!= null);
1085 } else if (right
is NullLiteral
){
1086 if (left
is NullLiteral
)
1087 return new BoolConstant (false);
1088 else if (left
is StringConstant
)
1089 return new BoolConstant (
1090 ((StringConstant
) left
).Value
!= null);
1092 if (left
is StringConstant
&& right
is StringConstant
){
1093 return new BoolConstant (
1094 ((StringConstant
) left
).Value
!=
1095 ((StringConstant
) right
).Value
);
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
);
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
);
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
);
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
);
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
);