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
;
206 Constant result
= null;
208 case Binary
.Operator
.BitwiseOr
:
209 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
210 if (left
== null || right
== null)
213 if (left
is IntConstant
){
215 int res
= ((IntConstant
) left
).Value
| ((IntConstant
) right
).Value
;
217 v
= new IntConstant (res
, left
.Location
);
218 if (result_type
== null)
221 return new EnumConstant (v
, result_type
);
222 } else if (left
is UIntConstant
){
224 uint res
= ((UIntConstant
)left
).Value
| ((UIntConstant
)right
).Value
;
226 v
= new UIntConstant (res
, left
.Location
);
227 if (result_type
== null)
230 return new EnumConstant (v
, result_type
);
231 } else if (left
is LongConstant
){
233 long res
= ((LongConstant
)left
).Value
| ((LongConstant
)right
).Value
;
235 v
= new LongConstant (res
, left
.Location
);
236 if (result_type
== null)
239 return new EnumConstant (v
, result_type
);
240 } else if (left
is ULongConstant
){
242 ulong res
= ((ULongConstant
)left
).Value
|
243 ((ULongConstant
)right
).Value
;
245 v
= new ULongConstant (res
, left
.Location
);
246 if (result_type
== null)
249 return new EnumConstant (v
, result_type
);
250 } else if (left
is UShortConstant
){
252 ushort res
= (ushort) (((UShortConstant
)left
).Value
|
253 ((UShortConstant
)right
).Value
);
255 v
= new UShortConstant (res
, left
.Location
);
256 if (result_type
== null)
259 return new EnumConstant (v
, result_type
);
260 } else if (left
is ShortConstant
){
262 short res
= (short) (((ShortConstant
)left
).Value
|
263 ((ShortConstant
)right
).Value
);
265 v
= new ShortConstant (res
, left
.Location
);
266 if (result_type
== null)
269 return new EnumConstant (v
, result_type
);
273 case Binary
.Operator
.BitwiseAnd
:
274 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
275 if (left
== null || right
== null)
278 if (left
is IntConstant
){
280 int res
= ((IntConstant
) left
).Value
& ((IntConstant
) right
).Value
;
282 v
= new IntConstant (res
, left
.Location
);
283 if (result_type
== null)
286 return new EnumConstant (v
, result_type
);
287 } else if (left
is UIntConstant
){
289 uint res
= ((UIntConstant
)left
).Value
& ((UIntConstant
)right
).Value
;
291 v
= new UIntConstant (res
, left
.Location
);
292 if (result_type
== null)
295 return new EnumConstant (v
, result_type
);
296 } else if (left
is LongConstant
){
298 long res
= ((LongConstant
)left
).Value
& ((LongConstant
)right
).Value
;
300 v
= new LongConstant (res
, left
.Location
);
301 if (result_type
== null)
304 return new EnumConstant (v
, result_type
);
305 } else if (left
is ULongConstant
){
307 ulong res
= ((ULongConstant
)left
).Value
&
308 ((ULongConstant
)right
).Value
;
310 v
= new ULongConstant (res
, left
.Location
);
311 if (result_type
== null)
314 return new EnumConstant (v
, result_type
);
315 } else if (left
is UShortConstant
){
317 ushort res
= (ushort) (((UShortConstant
)left
).Value
&
318 ((UShortConstant
)right
).Value
);
320 v
= new UShortConstant (res
, left
.Location
);
321 if (result_type
== null)
324 return new EnumConstant (v
, result_type
);
325 } else if (left
is ShortConstant
){
327 short res
= (short) (((ShortConstant
)left
).Value
&
328 ((ShortConstant
)right
).Value
);
330 v
= new ShortConstant (res
, left
.Location
);
331 if (result_type
== null)
334 return new EnumConstant (v
, result_type
);
338 case Binary
.Operator
.ExclusiveOr
:
339 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
340 if (left
== null || right
== null)
343 if (left
is IntConstant
){
345 int res
= ((IntConstant
) left
).Value ^
((IntConstant
) right
).Value
;
347 v
= new IntConstant (res
, left
.Location
);
348 if (result_type
== null)
351 return new EnumConstant (v
, result_type
);
352 } else if (left
is UIntConstant
){
354 uint res
= ((UIntConstant
)left
).Value ^
((UIntConstant
)right
).Value
;
356 v
= new UIntConstant (res
, left
.Location
);
357 if (result_type
== null)
360 return new EnumConstant (v
, result_type
);
361 } else if (left
is LongConstant
){
363 long res
= ((LongConstant
)left
).Value ^
((LongConstant
)right
).Value
;
365 v
= new LongConstant (res
, left
.Location
);
366 if (result_type
== null)
369 return new EnumConstant (v
, result_type
);
370 } else if (left
is ULongConstant
){
372 ulong res
= ((ULongConstant
)left
).Value ^
373 ((ULongConstant
)right
).Value
;
375 v
= new ULongConstant (res
, left
.Location
);
376 if (result_type
== null)
379 return new EnumConstant (v
, result_type
);
380 } else if (left
is UShortConstant
){
382 ushort res
= (ushort) (((UShortConstant
)left
).Value ^
383 ((UShortConstant
)right
).Value
);
385 v
= new UShortConstant (res
, left
.Location
);
386 if (result_type
== null)
389 return new EnumConstant (v
, result_type
);
390 } else if (left
is ShortConstant
){
392 short res
= (short)(((ShortConstant
)left
).Value ^
393 ((ShortConstant
)right
).Value
);
395 v
= new ShortConstant (res
, left
.Location
);
396 if (result_type
== null)
399 return new EnumConstant (v
, result_type
);
403 case Binary
.Operator
.Addition
:
404 bool left_is_string
= left
is StringConstant
;
405 bool right_is_string
= right
is StringConstant
;
408 // If both sides are strings, then concatenate, if
409 // one is a string, and the other is not, then defer
410 // to runtime concatenation
413 if (left_is_string
|| right_is_string
){
414 if (left_is_string
&& right_is_string
)
415 return new StringConstant (
416 ((StringConstant
) left
).Value
+
417 ((StringConstant
) right
).Value
, left
.Location
);
423 // handle "E operator + (E x, U y)"
424 // handle "E operator + (Y y, E x)"
426 // note that E operator + (E x, E y) is invalid
428 if (left
is EnumConstant
){
429 if (right
is EnumConstant
){
433 right
= right
.ToType (((EnumConstant
) left
).Child
.Type
, loc
);
438 } else if (right
is EnumConstant
){
439 left
= left
.ToType (((EnumConstant
) right
).Child
.Type
, loc
);
443 wrap_as
= right
.Type
;
447 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
448 if (left
== null || right
== null)
452 if (left
is DoubleConstant
){
455 if (ec
.ConstantCheckState
)
456 res
= checked (((DoubleConstant
) left
).Value
+
457 ((DoubleConstant
) right
).Value
);
459 res
= unchecked (((DoubleConstant
) left
).Value
+
460 ((DoubleConstant
) right
).Value
);
462 result
= new DoubleConstant (res
, left
.Location
);
463 } else if (left
is FloatConstant
){
466 if (ec
.ConstantCheckState
)
467 res
= checked (((FloatConstant
) left
).Value
+
468 ((FloatConstant
) right
).Value
);
470 res
= unchecked (((FloatConstant
) left
).Value
+
471 ((FloatConstant
) right
).Value
);
473 result
= new FloatConstant (res
, left
.Location
);
474 } else if (left
is ULongConstant
){
477 if (ec
.ConstantCheckState
)
478 res
= checked (((ULongConstant
) left
).Value
+
479 ((ULongConstant
) right
).Value
);
481 res
= unchecked (((ULongConstant
) left
).Value
+
482 ((ULongConstant
) right
).Value
);
484 result
= new ULongConstant (res
, left
.Location
);
485 } else if (left
is LongConstant
){
488 if (ec
.ConstantCheckState
)
489 res
= checked (((LongConstant
) left
).Value
+
490 ((LongConstant
) right
).Value
);
492 res
= unchecked (((LongConstant
) left
).Value
+
493 ((LongConstant
) right
).Value
);
495 result
= new LongConstant (res
, left
.Location
);
496 } else if (left
is UIntConstant
){
499 if (ec
.ConstantCheckState
)
500 res
= checked (((UIntConstant
) left
).Value
+
501 ((UIntConstant
) right
).Value
);
503 res
= unchecked (((UIntConstant
) left
).Value
+
504 ((UIntConstant
) right
).Value
);
506 result
= new UIntConstant (res
, left
.Location
);
507 } else if (left
is IntConstant
){
510 if (ec
.ConstantCheckState
)
511 res
= checked (((IntConstant
) left
).Value
+
512 ((IntConstant
) right
).Value
);
514 res
= unchecked (((IntConstant
) left
).Value
+
515 ((IntConstant
) right
).Value
);
517 result
= new IntConstant (res
, left
.Location
);
518 } else if (left
is DecimalConstant
) {
521 if (ec
.ConstantCheckState
)
522 res
= checked (((DecimalConstant
) left
).Value
+
523 ((DecimalConstant
) right
).Value
);
525 res
= unchecked (((DecimalConstant
) left
).Value
+
526 ((DecimalConstant
) right
).Value
);
528 result
= new DecimalConstant (res
, left
.Location
);
530 throw new Exception ( "Unexepected addition input: " + left
);
532 } catch (OverflowException
){
533 Error_CompileTimeOverflow (loc
);
537 return result
.TryReduce (ec
, wrap_as
, loc
);
541 case Binary
.Operator
.Subtraction
:
543 // handle "E operator - (E x, U y)"
544 // handle "E operator - (Y y, E x)"
545 // handle "U operator - (E x, E y)"
548 if (left
is EnumConstant
){
549 if (right
is EnumConstant
){
550 if (left
.Type
!= right
.Type
) {
551 Binary
.Error_OperatorCannotBeApplied (loc
, "-", left
.Type
, right
.Type
);
555 wrap_as
= TypeManager
.EnumToUnderlying (left
.Type
);
556 right
= ((EnumConstant
) right
).Child
.ToType (wrap_as
, loc
);
560 left
= ((EnumConstant
) left
).Child
.ToType (wrap_as
, loc
);
565 right
= right
.ToType (((EnumConstant
) left
).Child
.Type
, loc
);
571 } else if (right
is EnumConstant
){
572 left
= left
.ToType (((EnumConstant
) right
).Child
.Type
, loc
);
576 wrap_as
= right
.Type
;
579 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
580 if (left
== null || right
== null)
584 if (left
is DoubleConstant
){
587 if (ec
.ConstantCheckState
)
588 res
= checked (((DoubleConstant
) left
).Value
-
589 ((DoubleConstant
) right
).Value
);
591 res
= unchecked (((DoubleConstant
) left
).Value
-
592 ((DoubleConstant
) right
).Value
);
594 result
= new DoubleConstant (res
, left
.Location
);
595 } else if (left
is FloatConstant
){
598 if (ec
.ConstantCheckState
)
599 res
= checked (((FloatConstant
) left
).Value
-
600 ((FloatConstant
) right
).Value
);
602 res
= unchecked (((FloatConstant
) left
).Value
-
603 ((FloatConstant
) right
).Value
);
605 result
= new FloatConstant (res
, left
.Location
);
606 } else if (left
is ULongConstant
){
609 if (ec
.ConstantCheckState
)
610 res
= checked (((ULongConstant
) left
).Value
-
611 ((ULongConstant
) right
).Value
);
613 res
= unchecked (((ULongConstant
) left
).Value
-
614 ((ULongConstant
) right
).Value
);
616 result
= new ULongConstant (res
, left
.Location
);
617 } else if (left
is LongConstant
){
620 if (ec
.ConstantCheckState
)
621 res
= checked (((LongConstant
) left
).Value
-
622 ((LongConstant
) right
).Value
);
624 res
= unchecked (((LongConstant
) left
).Value
-
625 ((LongConstant
) right
).Value
);
627 result
= new LongConstant (res
, left
.Location
);
628 } else if (left
is UIntConstant
){
631 if (ec
.ConstantCheckState
)
632 res
= checked (((UIntConstant
) left
).Value
-
633 ((UIntConstant
) right
).Value
);
635 res
= unchecked (((UIntConstant
) left
).Value
-
636 ((UIntConstant
) right
).Value
);
638 result
= new UIntConstant (res
, left
.Location
);
639 } else if (left
is IntConstant
){
642 if (ec
.ConstantCheckState
)
643 res
= checked (((IntConstant
) left
).Value
-
644 ((IntConstant
) right
).Value
);
646 res
= unchecked (((IntConstant
) left
).Value
-
647 ((IntConstant
) right
).Value
);
649 result
= new IntConstant (res
, left
.Location
);
650 } else if (left
is DecimalConstant
) {
653 if (ec
.ConstantCheckState
)
654 res
= checked (((DecimalConstant
) left
).Value
-
655 ((DecimalConstant
) right
).Value
);
657 res
= unchecked (((DecimalConstant
) left
).Value
-
658 ((DecimalConstant
) right
).Value
);
660 return new DecimalConstant (res
, left
.Location
);
662 throw new Exception ( "Unexepected subtraction input: " + left
);
664 } catch (OverflowException
){
665 Error_CompileTimeOverflow (loc
);
669 return result
.TryReduce (ec
, wrap_as
, loc
);
673 case Binary
.Operator
.Multiply
:
674 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
675 if (left
== null || right
== null)
679 if (left
is DoubleConstant
){
682 if (ec
.ConstantCheckState
)
683 res
= checked (((DoubleConstant
) left
).Value
*
684 ((DoubleConstant
) right
).Value
);
686 res
= unchecked (((DoubleConstant
) left
).Value
*
687 ((DoubleConstant
) right
).Value
);
689 return new DoubleConstant (res
, left
.Location
);
690 } else if (left
is FloatConstant
){
693 if (ec
.ConstantCheckState
)
694 res
= checked (((FloatConstant
) left
).Value
*
695 ((FloatConstant
) right
).Value
);
697 res
= unchecked (((FloatConstant
) left
).Value
*
698 ((FloatConstant
) right
).Value
);
700 return new FloatConstant (res
, left
.Location
);
701 } else if (left
is ULongConstant
){
704 if (ec
.ConstantCheckState
)
705 res
= checked (((ULongConstant
) left
).Value
*
706 ((ULongConstant
) right
).Value
);
708 res
= unchecked (((ULongConstant
) left
).Value
*
709 ((ULongConstant
) right
).Value
);
711 return new ULongConstant (res
, left
.Location
);
712 } else if (left
is LongConstant
){
715 if (ec
.ConstantCheckState
)
716 res
= checked (((LongConstant
) left
).Value
*
717 ((LongConstant
) right
).Value
);
719 res
= unchecked (((LongConstant
) left
).Value
*
720 ((LongConstant
) right
).Value
);
722 return new LongConstant (res
, left
.Location
);
723 } else if (left
is UIntConstant
){
726 if (ec
.ConstantCheckState
)
727 res
= checked (((UIntConstant
) left
).Value
*
728 ((UIntConstant
) right
).Value
);
730 res
= unchecked (((UIntConstant
) left
).Value
*
731 ((UIntConstant
) right
).Value
);
733 return new UIntConstant (res
, left
.Location
);
734 } else if (left
is IntConstant
){
737 if (ec
.ConstantCheckState
)
738 res
= checked (((IntConstant
) left
).Value
*
739 ((IntConstant
) right
).Value
);
741 res
= unchecked (((IntConstant
) left
).Value
*
742 ((IntConstant
) right
).Value
);
744 return new IntConstant (res
, left
.Location
);
745 } else if (left
is DecimalConstant
) {
748 if (ec
.ConstantCheckState
)
749 res
= checked (((DecimalConstant
) left
).Value
*
750 ((DecimalConstant
) right
).Value
);
752 res
= unchecked (((DecimalConstant
) left
).Value
*
753 ((DecimalConstant
) right
).Value
);
755 return new DecimalConstant (res
, left
.Location
);
757 throw new Exception ( "Unexepected multiply input: " + left
);
759 } catch (OverflowException
){
760 Error_CompileTimeOverflow (loc
);
764 case Binary
.Operator
.Division
:
765 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
766 if (left
== null || right
== null)
770 if (left
is DoubleConstant
){
773 if (ec
.ConstantCheckState
)
774 res
= checked (((DoubleConstant
) left
).Value
/
775 ((DoubleConstant
) right
).Value
);
777 res
= unchecked (((DoubleConstant
) left
).Value
/
778 ((DoubleConstant
) right
).Value
);
780 return new DoubleConstant (res
, left
.Location
);
781 } else if (left
is FloatConstant
){
784 if (ec
.ConstantCheckState
)
785 res
= checked (((FloatConstant
) left
).Value
/
786 ((FloatConstant
) right
).Value
);
788 res
= unchecked (((FloatConstant
) left
).Value
/
789 ((FloatConstant
) right
).Value
);
791 return new FloatConstant (res
, left
.Location
);
792 } else if (left
is ULongConstant
){
795 if (ec
.ConstantCheckState
)
796 res
= checked (((ULongConstant
) left
).Value
/
797 ((ULongConstant
) right
).Value
);
799 res
= unchecked (((ULongConstant
) left
).Value
/
800 ((ULongConstant
) right
).Value
);
802 return new ULongConstant (res
, left
.Location
);
803 } else if (left
is LongConstant
){
806 if (ec
.ConstantCheckState
)
807 res
= checked (((LongConstant
) left
).Value
/
808 ((LongConstant
) right
).Value
);
810 res
= unchecked (((LongConstant
) left
).Value
/
811 ((LongConstant
) right
).Value
);
813 return new LongConstant (res
, left
.Location
);
814 } else if (left
is UIntConstant
){
817 if (ec
.ConstantCheckState
)
818 res
= checked (((UIntConstant
) left
).Value
/
819 ((UIntConstant
) right
).Value
);
821 res
= unchecked (((UIntConstant
) left
).Value
/
822 ((UIntConstant
) right
).Value
);
824 return new UIntConstant (res
, left
.Location
);
825 } else if (left
is IntConstant
){
828 if (ec
.ConstantCheckState
)
829 res
= checked (((IntConstant
) left
).Value
/
830 ((IntConstant
) right
).Value
);
832 res
= unchecked (((IntConstant
) left
).Value
/
833 ((IntConstant
) right
).Value
);
835 return new IntConstant (res
, left
.Location
);
836 } else if (left
is DecimalConstant
) {
839 if (ec
.ConstantCheckState
)
840 res
= checked (((DecimalConstant
) left
).Value
/
841 ((DecimalConstant
) right
).Value
);
843 res
= unchecked (((DecimalConstant
) left
).Value
/
844 ((DecimalConstant
) right
).Value
);
846 return new DecimalConstant (res
, left
.Location
);
848 throw new Exception ( "Unexepected division input: " + left
);
850 } catch (OverflowException
){
851 Error_CompileTimeOverflow (loc
);
853 } catch (DivideByZeroException
) {
854 Report
.Error (020, loc
, "Division by constant zero");
859 case Binary
.Operator
.Modulus
:
860 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
861 if (left
== null || right
== null)
865 if (left
is DoubleConstant
){
868 if (ec
.ConstantCheckState
)
869 res
= checked (((DoubleConstant
) left
).Value
%
870 ((DoubleConstant
) right
).Value
);
872 res
= unchecked (((DoubleConstant
) left
).Value
%
873 ((DoubleConstant
) right
).Value
);
875 return new DoubleConstant (res
, left
.Location
);
876 } else if (left
is FloatConstant
){
879 if (ec
.ConstantCheckState
)
880 res
= checked (((FloatConstant
) left
).Value
%
881 ((FloatConstant
) right
).Value
);
883 res
= unchecked (((FloatConstant
) left
).Value
%
884 ((FloatConstant
) right
).Value
);
886 return new FloatConstant (res
, left
.Location
);
887 } else if (left
is ULongConstant
){
890 if (ec
.ConstantCheckState
)
891 res
= checked (((ULongConstant
) left
).Value
%
892 ((ULongConstant
) right
).Value
);
894 res
= unchecked (((ULongConstant
) left
).Value
%
895 ((ULongConstant
) right
).Value
);
897 return new ULongConstant (res
, left
.Location
);
898 } else if (left
is LongConstant
){
901 if (ec
.ConstantCheckState
)
902 res
= checked (((LongConstant
) left
).Value
%
903 ((LongConstant
) right
).Value
);
905 res
= unchecked (((LongConstant
) left
).Value
%
906 ((LongConstant
) right
).Value
);
908 return new LongConstant (res
, left
.Location
);
909 } else if (left
is UIntConstant
){
912 if (ec
.ConstantCheckState
)
913 res
= checked (((UIntConstant
) left
).Value
%
914 ((UIntConstant
) right
).Value
);
916 res
= unchecked (((UIntConstant
) left
).Value
%
917 ((UIntConstant
) right
).Value
);
919 return new UIntConstant (res
, left
.Location
);
920 } else if (left
is IntConstant
){
923 if (ec
.ConstantCheckState
)
924 res
= checked (((IntConstant
) left
).Value
%
925 ((IntConstant
) right
).Value
);
927 res
= unchecked (((IntConstant
) left
).Value
%
928 ((IntConstant
) right
).Value
);
930 return new IntConstant (res
, left
.Location
);
932 throw new Exception ( "Unexepected modulus input: " + left
);
934 } catch (DivideByZeroException
){
935 Report
.Error (020, loc
, "Division by constant zero");
936 } catch (OverflowException
){
937 Error_CompileTimeOverflow (loc
);
942 // There is no overflow checking on left shift
944 case Binary
.Operator
.LeftShift
:
945 IntConstant ic
= right
.ToInt (loc
);
947 Binary
.Error_OperatorCannotBeApplied (loc
, "<<", lt
, rt
);
950 int lshift_val
= ic
.Value
;
953 if ((lic
= left
.ConvertToInt ()) != null)
954 return new IntConstant (lic
.Value
<< lshift_val
, left
.Location
);
957 if ((luic
= left
.ConvertToUInt ()) != null)
958 return new UIntConstant (luic
.Value
<< lshift_val
, left
.Location
);
961 if ((llc
= left
.ConvertToLong ()) != null)
962 return new LongConstant (llc
.Value
<< lshift_val
, left
.Location
);
965 if ((lulc
= left
.ConvertToULong ()) != null)
966 return new ULongConstant (lulc
.Value
<< lshift_val
, left
.Location
);
968 Binary
.Error_OperatorCannotBeApplied (loc
, "<<", lt
, rt
);
972 // There is no overflow checking on right shift
974 case Binary
.Operator
.RightShift
:
975 IntConstant sic
= right
.ToInt (loc
);
977 Binary
.Error_OperatorCannotBeApplied (loc
, ">>", lt
, rt
);
980 int rshift_val
= sic
.Value
;
983 if ((ric
= left
.ConvertToInt ()) != null)
984 return new IntConstant (ric
.Value
>> rshift_val
, left
.Location
);
987 if ((ruic
= left
.ConvertToUInt ()) != null)
988 return new UIntConstant (ruic
.Value
>> rshift_val
, left
.Location
);
991 if ((rlc
= left
.ConvertToLong ()) != null)
992 return new LongConstant (rlc
.Value
>> rshift_val
, left
.Location
);
995 if ((rulc
= left
.ConvertToULong ()) != null)
996 return new ULongConstant (rulc
.Value
>> rshift_val
, left
.Location
);
998 Binary
.Error_OperatorCannotBeApplied (loc
, ">>", lt
, rt
);
1001 case Binary
.Operator
.LogicalAnd
:
1002 if (left
is BoolConstant
&& right
is BoolConstant
){
1003 return new BoolConstant (
1004 ((BoolConstant
) left
).Value
&&
1005 ((BoolConstant
) right
).Value
, left
.Location
);
1009 case Binary
.Operator
.LogicalOr
:
1010 if (left
is BoolConstant
&& right
is BoolConstant
){
1011 return new BoolConstant (
1012 ((BoolConstant
) left
).Value
||
1013 ((BoolConstant
) right
).Value
, left
.Location
);
1017 case Binary
.Operator
.Equality
:
1018 if (left
is BoolConstant
&& right
is BoolConstant
){
1019 return new BoolConstant (
1020 ((BoolConstant
) left
).Value
==
1021 ((BoolConstant
) right
).Value
, left
.Location
);
1024 if (left
is NullLiteral
){
1025 if (right
is NullLiteral
)
1026 return new BoolConstant (true, left
.Location
);
1027 else if (right
is StringConstant
)
1028 return new BoolConstant (
1029 ((StringConstant
) right
).Value
== null, left
.Location
);
1030 } else if (right
is NullLiteral
){
1031 if (left
is NullLiteral
)
1032 return new BoolConstant (true, left
.Location
);
1033 else if (left
is StringConstant
)
1034 return new BoolConstant (
1035 ((StringConstant
) left
).Value
== null, left
.Location
);
1037 if (left
is StringConstant
&& right
is StringConstant
){
1038 return new BoolConstant (
1039 ((StringConstant
) left
).Value
==
1040 ((StringConstant
) right
).Value
, left
.Location
);
1044 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
1045 if (left
== null || right
== null)
1049 if (left
is DoubleConstant
)
1050 bool_res
= ((DoubleConstant
) left
).Value
==
1051 ((DoubleConstant
) right
).Value
;
1052 else if (left
is FloatConstant
)
1053 bool_res
= ((FloatConstant
) left
).Value
==
1054 ((FloatConstant
) right
).Value
;
1055 else if (left
is ULongConstant
)
1056 bool_res
= ((ULongConstant
) left
).Value
==
1057 ((ULongConstant
) right
).Value
;
1058 else if (left
is LongConstant
)
1059 bool_res
= ((LongConstant
) left
).Value
==
1060 ((LongConstant
) right
).Value
;
1061 else if (left
is UIntConstant
)
1062 bool_res
= ((UIntConstant
) left
).Value
==
1063 ((UIntConstant
) right
).Value
;
1064 else if (left
is IntConstant
)
1065 bool_res
= ((IntConstant
) left
).Value
==
1066 ((IntConstant
) right
).Value
;
1070 return new BoolConstant (bool_res
, left
.Location
);
1072 case Binary
.Operator
.Inequality
:
1073 if (left
is BoolConstant
&& right
is BoolConstant
){
1074 return new BoolConstant (
1075 ((BoolConstant
) left
).Value
!=
1076 ((BoolConstant
) right
).Value
, left
.Location
);
1078 if (left
is NullLiteral
){
1079 if (right
is NullLiteral
)
1080 return new BoolConstant (false, left
.Location
);
1081 else if (right
is StringConstant
)
1082 return new BoolConstant (
1083 ((StringConstant
) right
).Value
!= null, left
.Location
);
1084 } else if (right
is NullLiteral
){
1085 if (left
is NullLiteral
)
1086 return new BoolConstant (false, left
.Location
);
1087 else if (left
is StringConstant
)
1088 return new BoolConstant (
1089 ((StringConstant
) left
).Value
!= null, left
.Location
);
1091 if (left
is StringConstant
&& right
is StringConstant
){
1092 return new BoolConstant (
1093 ((StringConstant
) left
).Value
!=
1094 ((StringConstant
) right
).Value
, left
.Location
);
1097 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
1098 if (left
== null || right
== null)
1102 if (left
is DoubleConstant
)
1103 bool_res
= ((DoubleConstant
) left
).Value
!=
1104 ((DoubleConstant
) right
).Value
;
1105 else if (left
is FloatConstant
)
1106 bool_res
= ((FloatConstant
) left
).Value
!=
1107 ((FloatConstant
) right
).Value
;
1108 else if (left
is ULongConstant
)
1109 bool_res
= ((ULongConstant
) left
).Value
!=
1110 ((ULongConstant
) right
).Value
;
1111 else if (left
is LongConstant
)
1112 bool_res
= ((LongConstant
) left
).Value
!=
1113 ((LongConstant
) right
).Value
;
1114 else if (left
is UIntConstant
)
1115 bool_res
= ((UIntConstant
) left
).Value
!=
1116 ((UIntConstant
) right
).Value
;
1117 else if (left
is IntConstant
)
1118 bool_res
= ((IntConstant
) left
).Value
!=
1119 ((IntConstant
) right
).Value
;
1123 return new BoolConstant (bool_res
, left
.Location
);
1125 case Binary
.Operator
.LessThan
:
1126 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
1127 if (left
== null || right
== null)
1131 if (left
is DoubleConstant
)
1132 bool_res
= ((DoubleConstant
) left
).Value
<
1133 ((DoubleConstant
) right
).Value
;
1134 else if (left
is FloatConstant
)
1135 bool_res
= ((FloatConstant
) left
).Value
<
1136 ((FloatConstant
) right
).Value
;
1137 else if (left
is ULongConstant
)
1138 bool_res
= ((ULongConstant
) left
).Value
<
1139 ((ULongConstant
) right
).Value
;
1140 else if (left
is LongConstant
)
1141 bool_res
= ((LongConstant
) left
).Value
<
1142 ((LongConstant
) right
).Value
;
1143 else if (left
is UIntConstant
)
1144 bool_res
= ((UIntConstant
) left
).Value
<
1145 ((UIntConstant
) right
).Value
;
1146 else if (left
is IntConstant
)
1147 bool_res
= ((IntConstant
) left
).Value
<
1148 ((IntConstant
) right
).Value
;
1152 return new BoolConstant (bool_res
, left
.Location
);
1154 case Binary
.Operator
.GreaterThan
:
1155 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
1156 if (left
== null || right
== null)
1160 if (left
is DoubleConstant
)
1161 bool_res
= ((DoubleConstant
) left
).Value
>
1162 ((DoubleConstant
) right
).Value
;
1163 else if (left
is FloatConstant
)
1164 bool_res
= ((FloatConstant
) left
).Value
>
1165 ((FloatConstant
) right
).Value
;
1166 else if (left
is ULongConstant
)
1167 bool_res
= ((ULongConstant
) left
).Value
>
1168 ((ULongConstant
) right
).Value
;
1169 else if (left
is LongConstant
)
1170 bool_res
= ((LongConstant
) left
).Value
>
1171 ((LongConstant
) right
).Value
;
1172 else if (left
is UIntConstant
)
1173 bool_res
= ((UIntConstant
) left
).Value
>
1174 ((UIntConstant
) right
).Value
;
1175 else if (left
is IntConstant
)
1176 bool_res
= ((IntConstant
) left
).Value
>
1177 ((IntConstant
) right
).Value
;
1181 return new BoolConstant (bool_res
, left
.Location
);
1183 case Binary
.Operator
.GreaterThanOrEqual
:
1184 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
1185 if (left
== null || right
== null)
1189 if (left
is DoubleConstant
)
1190 bool_res
= ((DoubleConstant
) left
).Value
>=
1191 ((DoubleConstant
) right
).Value
;
1192 else if (left
is FloatConstant
)
1193 bool_res
= ((FloatConstant
) left
).Value
>=
1194 ((FloatConstant
) right
).Value
;
1195 else if (left
is ULongConstant
)
1196 bool_res
= ((ULongConstant
) left
).Value
>=
1197 ((ULongConstant
) right
).Value
;
1198 else if (left
is LongConstant
)
1199 bool_res
= ((LongConstant
) left
).Value
>=
1200 ((LongConstant
) right
).Value
;
1201 else if (left
is UIntConstant
)
1202 bool_res
= ((UIntConstant
) left
).Value
>=
1203 ((UIntConstant
) right
).Value
;
1204 else if (left
is IntConstant
)
1205 bool_res
= ((IntConstant
) left
).Value
>=
1206 ((IntConstant
) right
).Value
;
1210 return new BoolConstant (bool_res
, left
.Location
);
1212 case Binary
.Operator
.LessThanOrEqual
:
1213 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
1214 if (left
== null || right
== null)
1218 if (left
is DoubleConstant
)
1219 bool_res
= ((DoubleConstant
) left
).Value
<=
1220 ((DoubleConstant
) right
).Value
;
1221 else if (left
is FloatConstant
)
1222 bool_res
= ((FloatConstant
) left
).Value
<=
1223 ((FloatConstant
) right
).Value
;
1224 else if (left
is ULongConstant
)
1225 bool_res
= ((ULongConstant
) left
).Value
<=
1226 ((ULongConstant
) right
).Value
;
1227 else if (left
is LongConstant
)
1228 bool_res
= ((LongConstant
) left
).Value
<=
1229 ((LongConstant
) right
).Value
;
1230 else if (left
is UIntConstant
)
1231 bool_res
= ((UIntConstant
) left
).Value
<=
1232 ((UIntConstant
) right
).Value
;
1233 else if (left
is IntConstant
)
1234 bool_res
= ((IntConstant
) left
).Value
<=
1235 ((IntConstant
) right
).Value
;
1239 return new BoolConstant (bool_res
, left
.Location
);